/* An example of creating a window with an appropriate icon in win32, * by Paul van Genderen, 2005. * * This work is licensed under the Creative Commons Attribution License. * To view a copy of this license, visit * * http://creativecommons.org/licenses/by/2.5/ * * or send a letter to * * Creative Commons, * 559 Nathan Abbott Way, Stanford, * California 94305, * USA * * The code is written in pure ANSI C and is tested with mingw32. * Other compilers should work fine. * * With mingw32, it can be compiled as follows: * * gcc -c thisfile.c -o objectfile.o * windres -i private.rc --input-format=rc -o private.res -O coff * gcc main.o private.res -o "program.exe" -mwindows -s * * where private.rc points to an rc file with atleast one icon. * * This is not for newbies to GUI programming. If you are, try GTK+, version * 2.x or higher. IDE's that can handle GTK+ projects include Anjuta, * Dev-C++ and others. If you use Windows, download GTK+ here: * * http://gimp-win.sourceforge.net/stable.html * * Dev-C++ from here: * * http://www.bloodshed.net/ * * the packages for GTK and, if you like, other libraries from here: * * http://devpaks.org/ * * The GTK+ tutorial can be found here: * * http://www.gtk.org/tutorial/ * * Please donate to the Free Software Foundation. They promote the right to * use, study, copy, modify, and redistribute computer programs. They also * promote the development of free software, particularly the * GNU operating system and its GNU/Linux variants. They help to spread * awareness of the ethical and political issues of software freedom. * Nearly all of the funding for this work comes from individual donors. * Any donation amount is greatly appreciated, and all donations are * tax-deductible in the USA. * You can do so by joining as an associate member here: * * http://member.fsf.org/join?referrer=3101 * * Or in other ways, as outlined here: * * https://www.fsf.org/donate * * If you want to become an associate member, please use the * referrer code 3101. I would've used yours too. */ #define WIN32_LEAN_AND_MEAN #include #include const TCHAR szClassName[] = "AppClass"; const TCHAR szWindowName[] = "AppTitle"; ATOM atWndClass; HWND hWnd; HICON hIcon; /* Simple error message function, can be used anywhere to check * LastError(). Returns the actual error code too */ int ErrorHandler( void ) { LPVOID lpMsgBuf; DWORD dwError = GetLastError(); if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, (LPCVOID) NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, (DWORD) 0, (va_list *) NULL) == 0) ExitProcess(2147483547); MessageBox(NULL, (LPTSTR) lpMsgBuf, (LPTSTR) szWindowName, MB_OK|MB_ICONERROR|MB_SYSTEMMODAL); LocalFree((HLOCAL) lpMsgBuf); return (int) dwError; } /* This function should not be neccesary, but the ugly win32 * API requires it just to find out the resource number. */ BOOL CALLBACK enumResCb(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam) { assert(lpszType == RT_ICON); /* safe to delete */ /* icon resources always have an int as identifier */ memcpy((void *) lParam, (void *) &lpszName, sizeof(int)); /* make sure to stop enumerating */ return FALSE; } LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT ret=0; switch (message) { case WM_CREATE: break; case WM_DESTROY: PostQuitMessage(0); /* cleanup code */ break; default: ret = DefWindowProc (hwnd, message, wParam, lParam); } return ret; } int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nShow) { int ret; ret = (int) FALSE; hWnd = (HWND) NULL; /* Detect a previous instance */ hWnd=FindWindow(szClassName, NULL); if (hWnd == (HWND) NULL) { SetLastError(0); /* clear error */ { /* The following code is quite ugly, * and should've been much simpler. * But dealing with the fscked up win32 API * isn't simple either. */ /* the number of the resource to load */ int iResName; /* points to the resource found with the * number from the int above */ HRSRC hResID; hIcon = (HICON) NULL; iResName = 1; /* Enumerating only needs to be done once, * since the first icon needs to be loaded. * Feel free to extend or beautify this */ EnumResourceNames(NULL, RT_ICON, enumResCb, (LONG_PTR) &iResName); /* fetch a handler to the resource */ hResID = (HRSRC) NULL; hResID = FindResource((HMODULE) NULL, (LPTSTR) iResName, RT_ICON); if (hResID != (HRSRC) NULL) { /* now we got that, fetch the handler * to the actual data _in_ the * resource... */ HGLOBAL hResData = LoadResource( NULL, hResID); if (hResData != (HGLOBAL) NULL) { /* CreateIconFromResource doesn't know * how many bytes long it is, so yet * another function call has to be made. * However, that function call needs a * handle to the 'module' of this process */ HMODULE hMod = GetModuleHandle( (LPTSTR) NULL); if (hMod != (HMODULE) NULL) { /* Now the program has got a handle on * itself, get the size of the icon res */ DWORD dwSize = SizeofResource( hMod, hResID); if (dwSize) /* finally get the bloody icon */ hIcon = CreateIconFromResource( hResData, dwSize, TRUE, 0x00030000); /* don't change that number */ } FreeResource(hResData); } } } if (hIcon == NULL) hIcon = LoadIcon (NULL, IDI_APPLICATION); { WNDCLASSEX wincl; wincl.cbSize = sizeof (WNDCLASSEX); wincl.style = 0; /* use default */ wincl.lpfnWndProc = WindowProcedure; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hInstance = hThisInstance; wincl.hIcon = hIcon; wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); wincl.lpszMenuName = (LPCTSTR) NULL; wincl.lpszClassName = (LPCTSTR) szClassName; /* windows can figure out the small icon */ wincl.hIconSm = NULL; SetLastError(0); atWndClass = RegisterClassEx(&wincl); } if (atWndClass == 0) ret = ErrorHandler(); else { hWnd = CreateWindowEx( WS_EX_APPWINDOW, (LPCTSTR) szClassName, (LPCTSTR) szWindowName, WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, /* worry out the geometry later */ 100, 100, 400, 300, HWND_DESKTOP, (HMENU) NULL, hThisInstance, (LPVOID) NULL ); if (hWnd == (HWND) NULL) { UnregisterClass(szClassName, hThisInstance); ret = ErrorHandler(); } else { BOOL bRet; MSG messages; /* place widgets, set geometry */ ShowWindow(hWnd, nShow); /* ugly, but seems to be the way t * do it */ while ((bRet = GetMessage( &messages, (HWND) NULL, 0, 0)) > 0) { TranslateMessage(&messages); DispatchMessage(&messages); } ret = (bRet < 0 ? ErrorHandler() : messages.wParam); if (DestroyWindow(hWnd)) UnregisterClass(szClassName, hThisInstance); } } DestroyIcon(hIcon); } else /* Another instance is already running */ { if (IsIconic(hWnd)) ShowWindow(hWnd, SW_RESTORE); SetForegroundWindow (hWnd); } return ret; }