I need to make a few programs in C and i cannot get the window to work. Its come up with about 30 errors mostly saying ; is expected when there is one there, no storage class or type specifier, and declaration expected, not sure what these mean. I have looked at two turtorials and they both look extremely similar and mine looks the same, so not sure what these missing things are.
Heres my code
#include <windows.h>
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hThisInst,
HINSTANCE hPrevInst,
LPSTR lpszArgs,
int nWinMode);
{
WNDCLASS wcls;
HWND hwnd;
MSG msg;
LPCWSTR szClassName = L"ThreadsProgram";
LPCWSTR szWinName = L"My Threads Program"
//Register Class
wcls.style =0;
wcls.lpfnWndProc =WindowFunc;
wcls.cbClsExtra =0;
wcls.cbWndExtra =0;
wcls.hInstance =hThisInst;
wcls.hIcon =LoadIcon(NULL, IDI_APPLICATION);
wcls.hCursor =LoadCurser(NULL, IDC_ARROW);
wcls.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH);
wcls.lpszMenuName =NULL;
wcls.lpszClassName =szClassName;
if(!RegisterClass(&wcls))
{
MessageBox(NULL, "Window Registration Failed!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
//Make Window
hwnd = CreateWindow(szClassName,
szWinName,
WS_OVERLAPPINGWINDOW,
100,
100,
400,
400,
HWND_DESKTOP,
NULL,
hThisInst,
NULL);
//Show Window
if(hwnd == NULL)
{
MessageBox(NULL, "Window Failed!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nWinMode);
UpdateWindow(hwnd);
//Main Message Loop
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
The first problem I see is here:
int WINAPI WinMain(HINSTANCE hThisInst,
HINSTANCE hPrevInst,
LPSTR lpszArgs,
int nWinMode); /* <---- This semi-colon causes grief! */
{
WNDCLASS wcls;
You have a declaration of a function because of the semicolon after int nWinMode);.
Remove it.
There may also be other problems; I didn't look further and don't plan to do so. The compiler will guide you if your own code review won't help.
A lot of typos there.
semicolon after the WinMain
MessageBox() function taking 3 instead of 4 params.
LPWCSTR params
ShowWindow() with nCmdShow doesn't ... show
WS_OVERPLAPPEDWINDOW (not WS_OVERLAPPINGWINDOW)
LoadCursor instread of LoadCurser
Should work now. Next time type carefully
#include <windows.h>
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE: DestroyWindow(hwnd); break;
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
WNDCLASS wcls;
HWND hwnd;
MSG msg;
LPCSTR szClassName = "ThreadsProgram";
LPCSTR szWinName = "My Threads Program";
//Register Class
wcls.style =0;
wcls.lpfnWndProc =WindowFunc;
wcls.cbClsExtra =0;
wcls.cbWndExtra =0;
wcls.hInstance =hThisInst;
wcls.hIcon =LoadIcon(NULL, IDI_APPLICATION);
wcls.hCursor =LoadCursor(NULL, IDC_ARROW);
wcls.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH);
wcls.lpszMenuName =NULL;
wcls.lpszClassName =szClassName;
if(!RegisterClassA(&wcls))
{
MessageBoxA(NULL, 0, "Window Registration Failed!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
//Make Window
hwnd = CreateWindowA(szClassName, szWinName,
WS_OVERLAPPEDWINDOW,
100, 100, 400, 400,
HWND_DESKTOP,
NULL, hThisInst, NULL);
//Show Window
if(hwnd == NULL)
{
MessageBoxA(NULL, 0, "Window Failed!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, SW_SHOW/*nWinMode*/);
UpdateWindow(hwnd);
//Main Message Loop
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
Related
Question:
I am trying to set up the Winapi with C to display a simple window with the bare minimum of code, how do I do that in the way that my source code is formatted?
Issue:
The following does not open a window, it simply closes, why is this?
/* window_s.h */
typedef struct {
WNDCLASS wc;
HINSTANCE hInstance;
HWND hwnd;
} WINDOW;
/* setUpWinProc.h */
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg, WPARAM wParam,
LPARAM lParam) { }
/* registerWindow.c */
void registerWindow(WINDOW *window) {
const char CLASS_NAME[]
= "Window Class Name";
window->wc.lpfnWndProc = WindowProc;
window->wc.hInstance = window->wc.hInstance;
window->wc.lpszClassName = CLASS_NAME;
RegisterClass(&(window->wc));
}
/* createWindow.c */
int_fast64_t CreateWindow_(WINDOW *window) {
window->hwnd = CreateWindowEx(
0, // Optional window styles
window->wc.lpszClassName, // Window class
"Window", // Window text
WS_OVERLAPPEDWINDOW, //Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
window->hInstance, // Instance handle
NULL // Additional application data
);
if (window->hwnd == NULL)
return 0;
return window->hwnd;
}
/* Window_Main.c */
#include <windows.h>
#include "window_s.h"
#include "setUpWinProc.h"
#include "registerWindow.c"
#include "createWindow.c"
#include <stdio.h>
int WINAPI WinMain ( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR pCmdLine,
int nCmdShow ) {
WINDOW window = {{}, hInstance};
registerWindow(&window);
CreateWindow_(&window);
ShowWindow(window.hwnd, nCmdShow);
}
This is part of the issue:
int WINAPI WinMain ( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR pCmdLine,
int nCmdShow ) {
WINDOW window = {{}, hInstance};
registerWindow(&window);
CreateWindow_(&window);
ShowWindow(window.hwnd, nCmdShow);
}
What do you think happens after ShowWindow returns and WinMain itself returns? (Hint: the program exits).
Extend your WinMain to pump messages with TranslateMessage+DispatchMessage.
int WINAPI WinMain ( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR pCmdLine,
int nCmdShow ) {
MSG msg;
WINDOW window = {{}, hInstance};
registerWindow(&window);
CreateWindow_(&window);
ShowWindow(window.hwnd, nCmdShow);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Then your message proc needs to handle WM_CLOSE and WM_PAINT as a minimum and be able to forward to the default window proc for messages it doesn't handle.
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg, WPARAM wParam,
LPARAM lParam) {
switch (uMsg) {
case WM_PAINT: {
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY: {
PostQuitMessage(0);
break;
}
default: {
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
return 0;
}
Your RegisterClass call looks suspicous as well. Let's initialize like this:
WNDCLASSEXW wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WindowProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszClassName = szWindowClass;
RegisterClassExW(&wcex);
If you have Visual Studio (and edition), there's a default Win32 application that generates the most minimal of stub applications that does exactly what you are trying to achieve. Look for the C++ project for "Default Windows Application" or similar.
The core issue is here:
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg, WPARAM wParam,
LPARAM lParam) { }
As the compiler warned, this function needs to return a value (but isn't). The behavior of registering this as a window procedure is undefined. It will probably fail to create a window; CreateWindowEx() calls into the window procedure with WM_NCCREATE and WM_CREATE messages before it returns. Either message handler must return a particular value to continue window creation.
There's a similar issue with the window class name: It's using a local variable, but passes a pointer to it out. As registerWindow() returns, CLASS_NAME is gone. Class registration succeeds, but when it comes time to create the window, the call to CreateWindowEx() uses garbage as the window class name.
The first fix is thus:
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg, WPARAM wParam,
LPARAM lParam) {
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
and
void registerWindow(WINDOW *window) {
static const char CLASS_NAME[] = "Window Class Name";
// ...
}
That solves the window creation, though you won't see the window for long (if at all) because the code immediately falls out of WinMain() (which also needs to return a value), causing the process to terminate.
To fix that, you'll have to dispatch messages on the thread that created the window. The following will address both of these issues:
int WINAPI WinMain ( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR pCmdLine,
int nCmdShow ) {
WINDOW window = {{}, hInstance};
registerWindow(&window);
CreateWindow_(&window);
ShowWindow(window.hwnd, nCmdShow);
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0)) {
DispatchMessage(&msg);
}
return msg.wParam;
}
That's the bare minimum required (unless you count MessageBox() as "getting a window to open"). But it won't allow you to exit the application. To add that functionality, you'll want to add a WM_DESTROY handler that will signal the message loop to end, like so:
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg, WPARAM wParam,
LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
In one of my projects, I need to create a window in a non-main thread. I have never done that so I don't much experience on that.
According to the MSDN documentation and the SO question, I should be able to create a window in other thread, but I cannot succeed. Even though, in thread start routine, I register a window class, create a window and provide a message loop, the thread starts and exits immediately. In addition, I cannot debug the thread start routine so I cannot hit the break points inside it.
Is there something I am missing? I hope I don't miss anything silly.
Please consider the following demo. Thank you for taking your time.
#include <Windows.h>
#include <tchar.h>
HANDLE hThread;
DWORD WINAPI OtherUIThreadFunc(LPVOID args);
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND m_hwnd;
MSG msg;
WNDCLASSEX m_wcx;
const int MESSAGE_PROCESSED = 0;
const TCHAR* m_szClassName = _T("DemoWndCls");
const TCHAR* m_szWindowTitle = _T("Demo Window");
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int nCmdShow)
{
hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)OtherUIThreadFunc, hInstance, 0, NULL);
/*MSG msg;
ZeroMemory(&m_wcx, sizeof(m_wcx));
m_wcx.cbSize = sizeof(m_wcx);
m_wcx.style = CS_VREDRAW | CS_HREDRAW;
m_wcx.hInstance = hInstance;
m_wcx.lpszClassName = m_szClassName;
m_wcx.lpfnWndProc = WndProc;
m_wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
m_wcx.hbrBackground = (HBRUSH)COLOR_WINDOW;
if (!RegisterClassEx(&m_wcx))
return false;
m_hwnd = CreateWindowEx(0, m_wcx.lpszClassName, m_szWindowTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 480, 360, NULL, NULL, hInstance, NULL);
if (!m_hwnd)
return false;
ShowWindow(m_hwnd, SW_NORMAL);
UpdateWindow(m_hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;*/
}
DWORD WINAPI OtherUIThreadFunc(LPVOID args)
{
HINSTANCE hInstance = (HINSTANCE)args;
ZeroMemory(&m_wcx, sizeof(m_wcx));
m_wcx.cbSize = sizeof(m_wcx);
m_wcx.style = CS_VREDRAW | CS_HREDRAW;
m_wcx.hInstance = hInstance;
m_wcx.lpszClassName = m_szClassName;
m_wcx.lpfnWndProc = WndProc;
m_wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
m_wcx.hbrBackground = (HBRUSH)COLOR_WINDOW;
if (!RegisterClassEx(&m_wcx))
return false;
m_hwnd = CreateWindowEx(0, m_wcx.lpszClassName, m_szWindowTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 480, 360, NULL, NULL, hInstance, NULL);
if (!m_hwnd)
return false;
ShowWindow(m_hwnd, SW_NORMAL);
UpdateWindow(m_hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
return MESSAGE_PROCESSED;
case WM_DESTROY:
PostQuitMessage(0);
return MESSAGE_PROCESSED;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
Window creation succeeds (in theory, anyway). The issue is that the primary thread moves one to return, which causes the runtime to terminate the process.
To solve the issue you will have to keep the primary thread alive. A call to WaitForSingleObject, or a message loop are possible options.
This is mostly a result of following the conventions of C and C++. In either case returning from the main function is equivalent to calling the exit() function. This explains why returning from the primary thread tears down the entire process.
Bonus reading: If you return from the main thread, does the process exit?
First: I'm using Visual Studio 2010 on Windows XP - 32 Bit.
Right now I'm trying to write a DLL which will enable another application to work with low level keyboard hooks.
Even though I got it to work - I now want to understand why.
The non-working code:
#include <Windows.h>
#include <stdio.h>
static HINSTANCE hinst;
static HHOOK kbdHook = NULL;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
printf(":"); fflush(stdout);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
hinst = hinstDLL;
CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
kbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hinst, 0);
break;
case DLL_PROCESS_DETACH:
UnhookWindowsHookEx(kbdHook);
break;
default:
break;
}
return TRUE;
}
The working code:
#include <Windows.h>
#include <stdio.h>
static HINSTANCE hinst;
static HHOOK kbdHook = NULL;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
printf(":"); fflush(stdout);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
MSG msg;
kbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
hinst = hinstDLL;
CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
break;
case DLL_PROCESS_DETACH:
UnhookWindowsHookEx(kbdHook);
break;
default:
break;
}
return TRUE;
}
The only difference is that I moved the SetWindowsHookEx-call from DllMain to ThreadProc.
The question: Why does this make all the difference?
This is all explained in the documentation for LowLevelKeyboardProc callback function:
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
Your non-working code installs the hook on a thread, that doesn't run a message loop.
I'm trying to learn win32 API by following some tutorial.
(Though, I did very minor tweaking to create a borderless fixed window.)
However, my simplest window application is exiting with some random code.
I have no idea why it is not exiting with code '0'.
For extra information, I'm using Visual Studio 2012 Pro.
Source code's file extension is .c and the compiler setting is probably default.
I created the project as an empty win32 application (not console).
Please, some help will be appreciated.
Thank you.
#include <Windows.h>
#include <windowsx.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int __stdcall WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
INT nCmdShow) {
HWND hWnd;
WNDCLASSEX wcex;
MSG msg;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"WindowClass1";
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(
NULL,
L"Failed to register window!",
L"ERROR",
MB_OK | MB_ICONEXCLAMATION);
return EXIT_FAILURE;
}
hWnd = CreateWindowEx(
0,
L"WindowClass1",
L"Application",
WS_POPUP,
0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL, NULL, hInstance, NULL);
if (hWnd == NULL)
{
MessageBox(
NULL,
L"Failed to create window!",
L"ERROR",
MB_OK | MB_ICONEXCLAMATION);
return EXIT_FAILURE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, hWnd, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
In your program, GetMessage is in fact returning -1 which is an error condition. Your message loop terminates when GetMessage returns a value <=0, and so it terminates when GetMessage returns -1.
Now, because the final call to GetMessage fails with an error, the value of msg.wParam is not well-defined. You should not return it as an exit code. You should only return msg.wParam as an exit code when the final call to GetMessage returned 0. This is all made clear in the documentation.
You can see all this if you change your message loop to look like this:
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
return GetLastError();
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
On my machine, the bRet == -1 route is selected and the error code is 1400. Which is ERROR_INVALID_WINDOW_HANDLE. I'm not quite sure why your app is behaving in this way, but I'm content that I've answered the question you asked about exit codes!
Beyond covering the entire screen with a blank window, necessitating the use of ALT-F4 to exit your app, things look good, except for one thing:
GetMessage, despite claiming to return 'BOOL' actually returns int: some positive value when successful, 0 when WM_QUIT is received and -1 in the case of an error. Microsoft's policy of returning "BOOL plus a lil' something something" from GetMessage (and other functions) is stupid and dangerous for this reason, and they should be flogged for it.
If GetMessage returns -1 then the contents of msg may or may not be valid; in other words wParam may be zero or it may be potato. This could translate into the "random" exit codes you are seeing.
I suggest something like this:
int nRet;
do
{
nRet = GetMessage(&msg, hWnd, 0, 0);
if(nRet == -1)
return GetLastError();
if(nRet != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} while(nRet != 0);
return msg.wParam;
I'm trying to write a callback for my timer. I defined the TimerProc like this:
void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
//body of callback
}
and then the SetTimer defined like this:
myTimer = SetTimer(NULL,Timer_ID,30000,TimerProc);
my problem is that the callback never being called once the time elpassed (30 sec).
thank's for help.
SetTimer works by sending a WM_TIMER message to the default window procedure. Hence, as the MSDN states:
When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.
So make sure that you have a Message Loop running.
Quick test code. Works fine for me.
#include <windows.h>
static const TCHAR gc_szClassName[] = TEXT("Test");
static const TCHAR gc_szWindowTitle[] = TEXT("Test");
#define IDT_TIMER 0x100
VOID CALLBACK TimerProc(HWND hWnd, UINT uMessage, UINT_PTR uEventId, DWORD dwTime)
{
// display a message box to see the results of our beautiful program
MessageBox(hWnd, TEXT("This should pop up every 10 seconds.."), TEXT("Yay!"), MB_OK | MB_ICONINFORMATION);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
switch (uMessage)
{
case WM_CREATE:
// run every 10 seconds
SetTimer(hWnd, IDT_TIMER, 10000, TimerPRoc);
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
KillTimer(hWnd, IDT_TIMER);
PostQuitMessage(EXIT_SUCCESS);
break;
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCommandLine, int nShowCommand)
{
// define variables
HWND hWnd;
WNDCLASS wc;
MSG msg;
// unused parameters
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpszCommandLine);
UNREFERENCED_PARAMETER(nShowCommand);
// initialize WNDCLASS structure
ZeroMemory(&wc, sizeof(wc));
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = gc_szClassName;
// attempt to register the class
if (RegisterClass(&wc) != 0)
{
// attempt to create the window
hWnd = CreateWindow(gc_szClassName, gc_szWindowTitle, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL);
if (hWnd != NULL)
{
// retrieve messages
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// use the return-code from the window
return (int)msg.wParam;
}
}
return EXIT_FAILURE;
}