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
wxWorld Domination!
wxWorld Domination!
Posts: 1319
Joined: Mon Aug 30, 2004 6:01 pm

Post by Ryan Norton »

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
Moderator
Moderator
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE »

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
wxWorld Domination!
wxWorld Domination!
Posts: 1319
Joined: Mon Aug 30, 2004 6:01 pm

Post by Ryan Norton »

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:

Post by Sof_T »

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/c ... de-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

Post by Abysmalk »

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
Bryan Kelly
Earned some good credits
Earned some good credits
Posts: 117
Joined: Wed Apr 27, 2022 10:47 pm

Re:

Post by Bryan Kelly »

Ryan Norton wrote: Wed Nov 24, 2004 8:18 pm Help!!! I'm new/stuck and need a tutorial - NOW!
Robert Roebling’s Hello World returns a 404 not found
“a comprehensive wxWidgets … is a web page for Arnout Engelen
Beginners wxwidgets tutorial using Chinook returns a 404
Post Reply