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.
FAQ
- Ryan Norton
- wxWorld Domination!
- Posts: 1319
- Joined: Mon Aug 30, 2004 6:01 pm
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.
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.
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);
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
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
- Ryan Norton
- wxWorld Domination!
- Posts: 1319
- Joined: Mon Aug 30, 2004 6:01 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
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]
-
- Can't get richer than this
- Posts: 864
- Joined: Thu Jul 28, 2005 9:48 pm
- Location: New Forest, United Kingdom
- Contact:
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.
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/
Author of Programming with wxDevC++
http://sourceforge.net/projects/wxdevcpp-book/
Widgets in DLLs
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.hwxDLL.cppCode: 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() };
Note that the above is for 2.5.4 and up. For lower versions tryCode: 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!"); }
The following snippet is a simple "loader" for the DLL that does NOT use wxWidgets.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; }
DLLCaller.cppEdited by upCASE: Added new code sample and description.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; }
You may download the sources and a VC 7 project file here:
http://www.upcase.de/stuff/wxDLL_App.zip
-
- Earned some good credits
- Posts: 117
- Joined: Wed Apr 27, 2022 10:47 pm
Re:
Robert Roebling’s Hello World returns a 404 not foundRyan Norton wrote: ↑Wed Nov 24, 2004 8:18 pm Help!!! I'm new/stuck and need a tutorial - NOW!
- wxGuide by Otto Wyss: http://wxguide.sourceforge.net/index.html
- Robert Roebling's Hello World:http://www.wxwidgets.org/docs/tutorials/hello.htm
- A comprehensive wxWidgets tutorial: http://www.bzzt.net/~wxwindows/icpp_wx1.html
- The samples in the wxWidgets distribution also provide extensive examples how parts of wxWidgets can be used
- Some IBM ones: http://www-106.ibm.com/developerworks/l ... l=920,t=gr and http://www-106.ibm.com/developerworks/l ... in.html#h8
- Beginners wxwidgets tutorial using Chinook : German| English
“a comprehensive wxWidgets … is a web page for Arnout Engelen
Beginners wxwidgets tutorial using Chinook returns a 404