Well, i can sadly say that i have almost no experience with Windows API. It seems to be so confusing to me. I hope you guys can explain me what is going on.
I have the following code written in C:
What it pretty much does is to:
-Create a simple window
-Loads a bitmap with filename "exercising.bmp" to the created Window
So now, let's get over the code. First in wWinMain() function, the first thing it does is to fill up WNDCLASSEX{} structure and "register it as a class" using the function RegisterClassEx(). Then it uses the registered class' handle to create a window using CreateWindowA() function.
a) What exactly is the exact use of this RegisterClassEx()?
a.1 -As far i can tell is that it prepares the Window's structure information and registers it (to where does it register?) to be ready to create a Window. And i am not sure what exactly is this "class" they are referring to register.
a.2 -The big question is that why does it have to be a two step function in order to create a Window. Couldn't it be done in just CreateWindowA() where one of the parameters is the WNDCLASSEX{} structure? It just doesn't make sense to me to register (to wherever it goes) a structure. If i wanted re-usability, i can just re-use the original structure. If i wanted to have multiple window settings i could just have multiple structures. I mean, to have a structure i already need memory allocation. And to register the structure into a class, i need to use additional memory. Can't WindowClassEx() create a Window and register the structure in one go? What is the reason to have two separate functions?
So, after creating the window, it makes the created window visible using ShowWindow() function. Then it enters a while loop which checks for inputs associated with the window we just created. Before entering the while loop we cleared the MSG{} structure. So the first check for the while loop the ".message" item is not WM_QUIT and continues down. It peeks for messages in the queue, if there is any message translate it TranslateMessage() and dispatch it DispatchMessage(). But because we cleared the structure there should be nothing on the queue.
b) What does TranslateMessage() translate exactly? Maybe because my program is very simple, that it can work without this function. Can anyone offer me any simple example?
c) Since i don't see my WndProc() callback function called by me inside the wMainWin(), i believe DispatchMessage() is the one responsible to call WndProc().
c.1 -If i have multiple callback functions, how does DispatchMessage() determines which message corresponds to which callback function?
c.2 -Is it one message queue for the entire application even when i have multiple windows and callback functions?
c.3 -Within wWinMain(), I never invoked WndProc() manually nor invoked the message WM_PAINT. Yet a message requesting WM_PAINT to be dispatched to WndPro() was issued otherwise it would not show the bitmap on the window. And before any input is inserted, the MSG structure was initially emptied.
c.4 -Is there a multi-threaded background code working along with my application to read the window inputs or how does inputs get into the message queue i have in my application?
I have the following code written in C:
#include <windows.h>
HINSTANCE gInstance;
LRESULT CALLBACK WndProc(
HWND HandleWindow,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
PAINTSTRUCT PaintStruct;
HDC HandleDeviceContext;
HDC HDCBuffer;
HANDLE Image;
switch(message)
{
case WM_PAINT:
HandleDeviceContext = BeginPaint(HandleWindow, &PaintStruct);
Image = LoadImage(
NULL,
"exercising.bmp",
IMAGE_BITMAP,
384,
256,
LR_LOADFROMFILE
);
HDCBuffer = CreateCompatibleDC(HandleDeviceContext);
SelectObject(HDCBuffer, Image);
BitBlt(
HandleDeviceContext,
100,
100,
384,
246,
HDCBuffer,
0,
0,
SRCCOPY
);
DeleteDC(HDCBuffer);
DeleteObject(Image);
EndPaint(HandleWindow, &PaintStruct);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(
HandleWindow,
message,
wParam,
lParam);
}
return 0;
}
int WINAPI wWinMain(
HINSTANCE hInstance,
HINSTANCE prevInstance,
LPWSTR cmdLine,
int cmdShow)
{
gInstance = hInstance;
WNDCLASSEX WindowClass = {
sizeof(WNDCLASSEX),
CS_HREDRAW | CS_VREDRAW,
WndProc,
NULL, //cbClsExtra
NULL, //cbWndExtra
hInstance,
NULL, //hIcon
LoadCursor(NULL, IDC_ARROW), //hCursor
(HBRUSH)(COLOR_WINDOW+1), //hbrBackground
NULL, //lpszMenuName
"MainClass", //lpszClassName
NULL //hIconSm
};
RegisterClassEx(&WindowClass);
HWND HandleWindow = CreateWindowA(
"MainClass",
"WindowTitle",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL, //hWndParent
NULL, //hMenu
hInstance,
NULL //lpPraram
);
ShowWindow(HandleWindow, cmdShow);
MSG Message = {0};
while (Message.message != WM_QUIT)
{
if (PeekMessage(
&Message,
NULL, //HWND
NULL, //wMsgFilterMin
NULL, //wMsgFilterMax
PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}
UnregisterClass("MainClass", hInstance);
return static_cast<int>(Message.wParam);
}
What it pretty much does is to:
-Create a simple window
-Loads a bitmap with filename "exercising.bmp" to the created Window
So now, let's get over the code. First in wWinMain() function, the first thing it does is to fill up WNDCLASSEX{} structure and "register it as a class" using the function RegisterClassEx(). Then it uses the registered class' handle to create a window using CreateWindowA() function.
a) What exactly is the exact use of this RegisterClassEx()?
a.1 -As far i can tell is that it prepares the Window's structure information and registers it (to where does it register?) to be ready to create a Window. And i am not sure what exactly is this "class" they are referring to register.
a.2 -The big question is that why does it have to be a two step function in order to create a Window. Couldn't it be done in just CreateWindowA() where one of the parameters is the WNDCLASSEX{} structure? It just doesn't make sense to me to register (to wherever it goes) a structure. If i wanted re-usability, i can just re-use the original structure. If i wanted to have multiple window settings i could just have multiple structures. I mean, to have a structure i already need memory allocation. And to register the structure into a class, i need to use additional memory. Can't WindowClassEx() create a Window and register the structure in one go? What is the reason to have two separate functions?
So, after creating the window, it makes the created window visible using ShowWindow() function. Then it enters a while loop which checks for inputs associated with the window we just created. Before entering the while loop we cleared the MSG{} structure. So the first check for the while loop the ".message" item is not WM_QUIT and continues down. It peeks for messages in the queue, if there is any message translate it TranslateMessage() and dispatch it DispatchMessage(). But because we cleared the structure there should be nothing on the queue.
b) What does TranslateMessage() translate exactly? Maybe because my program is very simple, that it can work without this function. Can anyone offer me any simple example?
c) Since i don't see my WndProc() callback function called by me inside the wMainWin(), i believe DispatchMessage() is the one responsible to call WndProc().
c.1 -If i have multiple callback functions, how does DispatchMessage() determines which message corresponds to which callback function?
c.2 -Is it one message queue for the entire application even when i have multiple windows and callback functions?
c.3 -Within wWinMain(), I never invoked WndProc() manually nor invoked the message WM_PAINT. Yet a message requesting WM_PAINT to be dispatched to WndPro() was issued otherwise it would not show the bitmap on the window. And before any input is inserted, the MSG structure was initially emptied.
c.4 -Is there a multi-threaded background code working along with my application to read the window inputs or how does inputs get into the message queue i have in my application?
RegisterClass/RegisterClassEx registers a window's class. Every process has its own pool of registered window classes ready to be used. Every signle window is *of some class*. There are, for example, 'buttons', 'edits', etc. You create a button class, where you describe its behavior. And then you can create multiple windows of that class. It's true, of course, that you usually create only 1 "main window", so it may be strange to register a class just to create one window.
Another 'big' example of a window class are explorer's (not internet explorer's) windows. You can have multiple explorer windows - they are of the same class and they belong to one process (explorer.exe)*.
*it's possible to make them spawn in separate processes
TranslateMessage - there are some 'combinations' of messages that make their own specific sense. Most common example is WM_KEYDOWN/WM_KEYUP pair: When you quickly press and depress a key, you can translate it into a signle WM_KEYPRESS. Additionally, if that key corresponds to an ASCII character, you get WM_CHAR. Please read the remarks.
Every event generated in Windows OS relevant to your application's window is aded to that window's MESSAGE QUEUE. GetMessage waits for a message in that queue (enters 'efficient wait state'). As soon as there is a meesage, it *pops* that message and returns it. At this point you usually try to translate it, and the post it to your window. DispatchMessage is a convenient function which asks for the window's handle and then automagically gets that window procedure's address and calls it. It's because you more often that not DON'T know a window's procedure address. There are way to get wndproc's address, but it's easier to just call Dispatch Message. It does that or you.
A callback function is attached to a window's class. You specify it when you register it. And then that becomes the function called by 'Dispatch Message' with that class' window handle.
Please read these articles about messages and queues. It's really 'a must' in Windows OS. Seriously, make yourself a tea and read it.
Ad c4: It's not really 'multithreaded', but it's something -more or less- like that. Yes, there is 'something' that reads all events in the OS and adds the relevant ones to your window's message queue. It is the very definition of the Event-Driven OS: Every time there is something relevant to a window of your application, it gets posted to that window's message queue. Note that you may have multiple windows (even of the same class) and there might be an event which will be posted to one of your windows and not any other, for example (keypress in one window is an example - it's relevant to a window in which it took place).
It's late, so -like- 99% of it may be bullsh*t. Good night ^^
Another 'big' example of a window class are explorer's (not internet explorer's) windows. You can have multiple explorer windows - they are of the same class and they belong to one process (explorer.exe)*.
*it's possible to make them spawn in separate processes
TranslateMessage - there are some 'combinations' of messages that make their own specific sense. Most common example is WM_KEYDOWN/WM_KEYUP pair: When you quickly press and depress a key, you can translate it into a signle WM_KEYPRESS. Additionally, if that key corresponds to an ASCII character, you get WM_CHAR. Please read the remarks.
Every event generated in Windows OS relevant to your application's window is aded to that window's MESSAGE QUEUE. GetMessage waits for a message in that queue (enters 'efficient wait state'). As soon as there is a meesage, it *pops* that message and returns it. At this point you usually try to translate it, and the post it to your window. DispatchMessage is a convenient function which asks for the window's handle and then automagically gets that window procedure's address and calls it. It's because you more often that not DON'T know a window's procedure address. There are way to get wndproc's address, but it's easier to just call Dispatch Message. It does that or you.
A callback function is attached to a window's class. You specify it when you register it. And then that becomes the function called by 'Dispatch Message' with that class' window handle.
Please read these articles about messages and queues. It's really 'a must' in Windows OS. Seriously, make yourself a tea and read it.
Ad c4: It's not really 'multithreaded', but it's something -more or less- like that. Yes, there is 'something' that reads all events in the OS and adds the relevant ones to your window's message queue. It is the very definition of the Event-Driven OS: Every time there is something relevant to a window of your application, it gets posted to that window's message queue. Note that you may have multiple windows (even of the same class) and there might be an event which will be posted to one of your windows and not any other, for example (keypress in one window is an example - it's relevant to a window in which it took place).
It's late, so -like- 99% of it may be bullsh*t. Good night ^^
You can create a window in one step, if you are happy to use one of the native window classes (includes those known as Common Controls) eg EDIT is a box for entering some text.
You can also create a window in one step if you have prepared a "dialog resource" (see Dialog Windows). This is basically some data embedded in your executable which describes the window and its subwindows (child controls). A lot like a "form", really.
Registering a window class is only necessary if your application contains no resource information and you wish to create a window whose function and form differ greatly from the ones you can choose from.
The final options are called 'subclassing' and 'superclassing', and basically involve modifying/extending the behavior of a defined window class.
You can also create a window in one step if you have prepared a "dialog resource" (see Dialog Windows). This is basically some data embedded in your executable which describes the window and its subwindows (child controls). A lot like a "form", really.
Registering a window class is only necessary if your application contains no resource information and you wish to create a window whose function and form differ greatly from the ones you can choose from.
The final options are called 'subclassing' and 'superclassing', and basically involve modifying/extending the behavior of a defined window class.
To get more into c4...
Basically each thread has a message queue. Windows messages are a way to communicate between threads/processes (see for example PostThreadMessage).
Window messages are placed into the queue of the thread that created the window.
It works in a few steps. Namely, when you press a key or do something with the mouse, the event will first come in via the device driver, which places it onto the system message queue. After all, the keyboard or mouse doesn't know anything about applications or windows. It's just very basic information of "key X is pressed" or "mouse moved by X units horizontally and Y units vertically".
The system will then figure out what application/window is active/was clicked in/etc, and places the message in the proper thread's queue.
So in that sense it is multithreaded: each application has at least one thread, and then there is the lowlevel system event handling code, which can also be seen as a separate thread.
Basically each thread has a message queue. Windows messages are a way to communicate between threads/processes (see for example PostThreadMessage).
Window messages are placed into the queue of the thread that created the window.
It works in a few steps. Namely, when you press a key or do something with the mouse, the event will first come in via the device driver, which places it onto the system message queue. After all, the keyboard or mouse doesn't know anything about applications or windows. It's just very basic information of "key X is pressed" or "mouse moved by X units horizontally and Y units vertically".
The system will then figure out what application/window is active/was clicked in/etc, and places the message in the proper thread's queue.
So in that sense it is multithreaded: each application has at least one thread, and then there is the lowlevel system event handling code, which can also be seen as a separate thread.