FAQ

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
User avatar
Ryan Norton
Moderator
Moderator
Posts: 1319
Joined: Mon Aug 30, 2004 6:01 pm

Postby Ryan Norton » Thu Oct 27, 2005 8:32 pm

Why is my program so big?

An unfortunate side-effect of using wxWidgets is that you'll have big applications. Even the smallest application can run close to a megabyte. You're best bet is to use UPX or a similar program to compress your program if that is a problem for you.

Or in the future use upCASE's wxWidgets setup compiler. It can switch off specific components and compile the library smaller and tailored to your design.
[Mostly retired moderator, still check in to clean up some stuff]

upCASE
Site Admin
Site Admin
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Postby upCASE » Fri Mar 17, 2006 8:55 am

How do I take a screenshot?

In order to take a screenshot of the whole screen, a specific window, or just a part of one of them, you'll need to use at least two wxDCs.
This example takes a screenshot of the whole screen and saves it as a JPEG image named screenshot.jpg afterwards.

Code: Select all

   //Create a DC for the whole screen area
   wxScreenDC dcScreen;

   //Get the size of the screen/DC
   wxCoord screenWidth, screenHeight;
   dcScreen.GetSize(&screenWidth, &screenHeight);

   //Create a Bitmap that will later on hold the screenshot image
   //Note that the Bitmap must have a size big enough to hold the screenshot
   //-1 means using the current default colour depth
   wxBitmap screenshot(screenWidth, screenHeight,-1);

   //Create a memory DC that will be used for actually taking the screenshot
   wxMemoryDC memDC;
   //Tell the memory DC to use our Bitmap
   //all drawing action on the memory DC will go to the Bitmap now
   memDC.SelectObject(screenshot);
   //Blit (in this case copy) the actual screen on the memory DC
   //and thus the Bitmap
   memDC.Blit( 0, //Copy to this X coordinate
            0, //Copy to this Y coordinate
            screenWidth, //Copy this width
            screenHeight, //Copy this height
            &dcScreen, //From where do we copy?
            0, //What's the X offset in the original DC?
            0  //What's the Y offset in the original DC?
         );
   //Select the Bitmap out of the memory DC by selecting a new
   //uninitialized Bitmap
   memDC.SelectObject(wxNullBitmap);

   //Our Bitmap now has the screenshot, so let's save it :-)
   screenshot.SaveFile("screenshot.jpg",wxBITMAP_TYPE_JPEG);

Note that for saving the bitmap as a JPEG image you'll need to initialize the JPEG handler first.

To create a screenshot of a window you would go about the same way. Instead of a wxScreenDC you'd use a wxWindowDC for the window you want to take a screenshot of.
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda

User avatar
Ryan Norton
Moderator
Moderator
Posts: 1319
Joined: Mon Aug 30, 2004 6:01 pm

Postby Ryan Norton » Thu Jun 15, 2006 5:55 pm

Why does wxSocket/wxURL/wxFileSystem/wxHTMLWindow not work in wxApp::OnInit on Windows?

In wxWidgets, there is a global instance of a class called wxEventLoop. While this class is "running", it handles both platform-specific events and wxWidgets events.

However, the global event loop is not run until after wxApp::OnInit is done.

Normally, this isn't a problem, as events just get queued. The problem with the wxSocket implementation on windows is that it uses a WinAPI windows callback to handle certain messages, and expects the events at times to be handled immediately. If they don't, it may fail, hang, and/or crash.

The gist of it is - you can't use wxSocket-related stuff in wxApp::OnInit on Windows.

See this thread on the developer's mailing list:
http://lists.wxwidgets.org/cgi-bin/ezml ... hgbaehcf#b
[Mostly retired moderator, still check in to clean up some stuff]

Sof_T
Can't get richer than this
Can't get richer than this
Posts: 864
Joined: Thu Jul 28, 2005 9:48 pm
Location: New Forest, United Kingdom
Contact:

Postby Sof_T » Thu Oct 05, 2006 2:12 pm

I came across a problem while trying to compile an application that was built using an ANSI build with a Unicode build. The project used XRC and the compiler complained about pasting 'L' or 'LL'. I found the answer here http://litwindow.blogspot.com/2005/12/compile-error-using-xrc-and-unicode-vc.html

I reproduce the text here in case the site is down.

You are using wxWidgets XRC Resources and compile a Unicode application (which is default on Visual Studio 8.0 Express) and are getting an error similar to

xrcdemo.cpp:63:1: pasting "LL" and "L"UsernameField"" does not give a valid preprocessing token
xrcdemo.cpp: In member function `void LoginDialog::InitWidgetsFromXRC()':

The error is in how you are using the XRC macros. XRC macros don't accept string constants enclosed in _T(). Use string contants without _T(), even in Unicode builds.

Summary: Use _T() with XRC methods, do not use _T() with XRC macros.


Suppose you have

wxXmlResource::Get()->LoadDialog(this, NULL, _T("LoginDialog"));
UsernameField = XRCCTRL(*this, _T("UsernameField"), wxTextCtrl);



You must enclose strings in _T(), if you want to be able to compile your application in both, ANSI and Unicode builds. So LoadDialog(this, NULL, _T("LoginDialog")); is the correct way to specify 'LoginDialog' as the XRC resource.

But, the XRC macros that take a string use _T() internally already. So XRCCTRL(*this, _T("UsernameField"), wxTextCtrl) is wrong, because XRCCTRL is a macro and it adds _T() to the 'UsernameField' parameter itself. The compiler then sees something like

xrcctrl_function(*this, _T( _T("UsernameField") ), wxTextCtrl)



and prints an error.

The correct use of the XRCCTRL and similar macros is to pass in strings without _T(), even in Unicode builds.

UsernameField = XRCCTRL(*this, "UsernameField"), wxTextCtrl);


Some more background for the interested: _T() is a simple macro that simply adds the literal 'L' in front of a quoted string in Unicode builds and does nothing in ANSI builds. Unicode strings are wide-character strings (wchar_t). Wide-character string constants must be preceded by an L in C++.

"This is a char string (1byte), or ANSI string"
L"This is a wide-char string (2byte/4byte under linux), or Unicode string"



Using XRCCTRL(*this, _T("UsernameField"), wxTextCtrl) would expand to xrcctrl_function(*this, LL"UsernameField", wxTextCtrl), which is what the compiler error message says.
The home of Sof.T http://www.sof-t.site88.net/
Author of Programming with wxDevC++
http://sourceforge.net/projects/wxdevcpp-book/

Abysmalk
In need of some credit
In need of some credit
Posts: 2
Joined: Thu May 22, 2008 3:31 pm

Widgets in DLLs

Postby Abysmalk » Mon May 26, 2008 8:04 pm

Following is Ryan Norton's guide on how to make a dll in wxWdigets, however there have been some changes in recent version so my question is two fold. First how do I make changes to allow the code to work with wxWidgets 2.8.7. And second how would I post a wx widget like a combo box to the window that is pointed to by HWND?


Ryan Norton wrote:How do I make a dll for use with wxWidgets?

The following sample shows how to implement a DLL using wxWidgets. When called it will initialize wxWidgets and clean it on unload. The DLL exports two functions "DLLFunction" and "TestReport". DLLFunction displays a simple dialog with a button and handles the button event. "TestReport" shows a small dialog with a wxHTML page.

wxDLL.h

Code: Select all

// wxDLL is a simple DLL which demonstrates how to use
// wxWindows in a DLL which is called from another
// application (not using wxWindows)
//
//
// Tony Edgecombe
// (C) 2004 Frogmore Computer Services
// www.frogmorecs.com
// Edited by upCASE

#pragma once

#include "wx/wx.h"

#include "windows.h"


#ifdef DLLFUNCTIONS_EXPORTS
#define DLLFUNCTIONS_API __declspec(dllexport)
#else
#define DLLFUNCTIONS_API __declspec(dllimport)
#endif

extern "C" DLLFUNCTIONS_API void DLLFunction(HWND);
extern "C" DLLFUNCTIONS_API void TestReport(HWND handle);

class wxDLLApp : public wxApp
{
   bool OnInit();
   void OnButton(wxCommandEvent& evt);
   DECLARE_EVENT_TABLE()
};


wxDLL.cpp

Code: Select all

// wxDLL is a simple DLL which demonstrates how to use
// wxWindows in a DLL which is called from another
// application (not using wxWindows)

// Edited by upCASE

#include "wx/wx.h"

#include "wxDLL.h"
#include "wx/wxhtml.h"

// We use IMPLEMENT_APP_NO_MAIN so we can start the app from DllMain
// as we don't have a WinMain or main entry point
//
BEGIN_EVENT_TABLE(wxDLLApp, wxApp)
   EVT_BUTTON(123,wxDLLApp::OnButton)
END_EVENT_TABLE()

IMPLEMENT_APP_NO_MAIN(wxDLLApp)

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                )
{
   switch (ul_reason_for_call)
   {
      case DLL_PROCESS_ATTACH:
      {   //use wxInitialize() if you don't want GUI instead of the following 12 lines
                        wxSetInstance((HINSTANCE)hModule);
         int argc = 0;
         char **argv = NULL;
         wxEntryStart(argc, argv);
         if ( !wxTheApp || !wxTheApp->CallOnInit() )
            return FALSE;
      }
      break;

      case DLL_THREAD_ATTACH:
      break;

      case DLL_THREAD_DETACH:
      break;

      case DLL_PROCESS_DETACH:
       wxEntryCleanup(); //use wxUninitialize() if you don't want GUI
      break;
   }
    return TRUE;
}

// extern "C" so we don't need a DEF file

// This is the function to be called from the host app
extern "C" DLLFUNCTIONS_API void DLLFunction(HWND handle)
{
// Create a dummy wxWindow so we can use the HWND passed from the
// host application

   wxWindow win;
   win.SetHWND((WXHWND)handle);
   win.Enable(false);

   wxDialog dlg(&win, -1, "wxDialog in DLL", wxDefaultPosition, wxSize(150,150));
   wxButton b(&dlg, 123,"Press me please");
   dlg.ShowModal();

// Clean up else the caller can't use its window
   win.Enable(true);
   win.SetHWND(0);
}

extern "C" DLLFUNCTIONS_API void TestReport(HWND handle)
{
   wxWindow win;

   win.SetHWND((WXHWND)handle);
   win.Enable(false);

   wxDialog dlg(&win, wxID_ANY, wxString(_("About")), wxDefaultPosition, wxSize(400,180));
   
   wxHtmlWindow html1(&dlg,wxID_ANY, wxDefaultPosition, wxSize(380, 160), wxHW_SCROLLBAR_NEVER);
   html1.SetPage("<html><body>"
                     "<h1>Error</h1>"
               "Some error occurred :-))"
               "</body></hmtl>");

   dlg.ShowModal();

   // Clean up else the caller can't use its window
   win.Enable(true);
   win.SetHWND(0);
}

bool wxDLLApp::OnInit()
{
   return true;
}
void wxDLLApp::OnButton(wxCommandEvent& evt)
{
   wxMessageBox("You really did it.... I don't believe it!");
}


Note that the above is for 2.5.4 and up. For lower versions try

Code: Select all

BOOL APIENTRY DllMain( HINSTANCE hModule,
                       DWORD  fdwReason,
                       LPVOID lpReserved
                                        )
{
   switch (fdwReason)
   {
   case DLL_PROCESS_ATTACH:
       {
           wxEntry(hModule, 0, NULL, 0, false);
       }
       break;

   case DLL_PROCESS_DETACH:
       {
           wxTheApp->OnExit();
           wxApp::CleanUp();
       }
   }

    return TRUE;
}


The following snippet is a simple "loader" for the DLL that does NOT use wxWidgets.
DLLCaller.cpp

Code: Select all

// This is a simple Windows app which loads and calls our DLL on request
//
// Tony Edgecombe
// (C) 2004 Frogmore Computer Services Ltd
// www.frogmorecs.com
// Edited by upCASE

#pragma once

#include "windows.h"

int APIENTRY WinMain(HINSTANCE hInstance,
                  HINSTANCE hPrevInstance,
                  LPTSTR    lpCmdLine,
                  int       nCmdShow);

// Just a test app no real need for seperate .h file
// #include "DLLTestApp.h"

#include "assert.h"

typedef void (*DLLFunctionPtr) (HWND);
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);

// Entry point
int APIENTRY WinMain(HINSTANCE hInstance,
                  HINSTANCE hPrevInstance,
                  LPTSTR    lpCmdLine,
                  int       nCmdShow)
{
   WNDCLASSEX wcx;

   wcx.cbSize = sizeof(wcx);
   wcx.style = CS_HREDRAW | CS_VREDRAW;
   wcx.lpfnWndProc = MainWndProc;
   wcx.cbClsExtra = 0;
   wcx.cbWndExtra = 0;
   wcx.hInstance = hInstance;
   wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
   wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
   wcx.hbrBackground = (HBRUSH)( COLOR_WINDOW+1 );
   wcx.lpszMenuName =  "MainMenu";
   wcx.lpszClassName = "MainWClass";
   wcx.hIconSm = NULL;

   ATOM a = RegisterClassEx(&wcx);
   assert(a);

   HWND hwnd = CreateWindow("MainWClass",
                     "Test DLL",
                     WS_OVERLAPPEDWINDOW,
                     CW_USEDEFAULT,
                     CW_USEDEFAULT,
                     CW_USEDEFAULT,
                     CW_USEDEFAULT,
                     (HWND) NULL,
                     (HMENU) NULL,
                     hInstance,
                     (LPVOID) NULL);
   assert(hwnd);

   ShowWindow(hwnd, nCmdShow);
   UpdateWindow(hwnd);

   long bRet;
   MSG msg;
   while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0 )
   {
      if (bRet != -1)
      {
         TranslateMessage( &msg );
         DispatchMessage( &msg );
      }
   }

   return 0;
}

// Windows Callback Procedure
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   PAINTSTRUCT ps;
   HDC hDC;

   switch( msg ) {
     case WM_PAINT:
        hDC = BeginPaint( hWnd, &ps );
        TextOut( hDC, 10, 10, "Left Click on this form to launch function: DLLFunction", 55 );
        TextOut( hDC, 10, 30, "Right Click on this form to launch function: TestReport", 55 );
        EndPaint( hWnd, &ps );
        break;

     case WM_DESTROY:
        PostQuitMessage( 0 );
        break;

     case WM_LBUTTONUP:
        {
           // Load up the DLL and call DLLFunction(
            HMODULE hModule = LoadLibrary("Test.dll");
            assert(hModule);
            DLLFunctionPtr pProc = (DLLFunctionPtr)GetProcAddress(hModule, "DLLFunction");
            assert(pProc);
            (pProc)(hWnd);
            FreeLibrary(hModule);
        }
        break;

     case WM_RBUTTONUP:
        {
           // Load up the DLL and call DLLFunction(
            HMODULE hModule = LoadLibrary("Test.dll");
            assert(hModule);
            DLLFunctionPtr pProc = (DLLFunctionPtr)GetProcAddress(hModule, "TestReport");
            assert(pProc);
            (pProc)(hWnd);
            FreeLibrary(hModule);
        }
        break;

     default:
        return( DefWindowProc( hWnd, msg, wParam, lParam ));
   }
   return 0;
}


Edited by upCASE: Added new code sample and description.

You may download the sources and a VC 7 project file here:
http://www.upcase.de/stuff/wxDLL_App.zip


Return to “C++ Development”

Who is online

Users browsing this forum: No registered users and 16 guests