|
Free Educational Resource Center for teachers and students. Includes Interviews, Sourcecode, Free Software, Research Papers, Articles, Tutorials and much more.. |
R E S E A R C H A C T I V I T Y . C O M
Our Fellow Research Center for Ph.D Schollars |
|
| Home About Submit & Earn | Archives: C And C + + Programming » Dev Packages » Interviews » Php Mysql Programming » Windows Programming | |
|
Windows Programming > start windows programming win32 api basics
Start Windows Programming (winapi/win32 Api basics) If you read documents one by one carefully and do not skip any part, then it is somehow guarantee that you will be able to program any kind of windows application, even your own framework like MFC, OWL, GTK+, RAD C++, FLTK, etc.
Messaging and Notification architecture: Windows programming becomes so easier once you get to know the basic architecture behid every GUI based program that runs on Microsoft Windows. Microsoft Windows operating system entirely works on messaging and notification architecture. You must have noticed many kind of Dialogs, controls, and other visual objects in windows, each and everyone of them is basically a "Window", that is the reason this operating system is called windows. From creation of a window up-to its destruction (upon program exit), the window sends and receives messages. Why am I using two different words 'messages' and 'notifications'? to make you understand few things later. Either to track some event occured on any window or to manipulate a window, you will have to use messages. Messages are specific to each kind of window, but some messages can be part of any kind of window, we will discuss in upcoming readings. When there many messages are being sent simulaneously, the windows creates a queue of them, and dispatches them one by one. Let me give you very simple examples that will make you understand a windows' program structure. 1. There is always a main program. We create several kind of windows and controls in it; main program which has a loop which checks if there is a message in queue, if there is, then forward/dispatch the message. Loop terminates/breaks when there is a quit message. 2. Each window has its own window procedure attached, in which we (developers) receive notifications either from other windows, operating system, or even from its own child controls (e.g. notification about user has changed/typed text in the textbox), and if required, we send messages at certain point to manipulate windows (e.g. changing text in text box programatially). Now when it is about procedures of controls, it is the same. e.g. A Button or a Text box has its own procedure that we do not disturb. Controls are also little windows, but procedures for controls are already been defined by operating system, so we let them be as they are, so that they function as required. In some case we can add additional functionlity to controls by attaching our custom window procedure to them, this kind of practice is called sub-classing (which we will discuss later). The main program in windows is a bit different than the traditional int main() (we will discuss this later so that you do not get confused). Don't worry, for now keep using same main function as shown below. A windows main program looks something like this:
Some about windows types with new names:
Creating Windows and Controls: You must have noticed many kind of Dialogs, controls, and other visual objects in windows, each and everyone of them is basically a "window", that is the reason this operating system is called windows. e.g. When you open a text file using notedpad, there is one main window, and the text area that contains the text, this text area is another window. Now, when creating windows it is your responsibility to create window of specific type. First I need to get you started programming easily, then we will move to some important things that will require polishing existing code, such as int main() to int APIENTRY WinMain(....), window class registration etc etc. Let's get started with our first program, that will display a dialog, then a message box, and when messages box is closed, the program exits. We will be using winapi function CreateWindowEx throughout the document for creating all kind of windows, either main window or a control. And, use function MessageBox to display a message on screen. First of all make sure to include header file windows.h which includes all the informtion regarding windows API basics and functions that allow us to access the low level functionality. And btw, following code looks big, but actually is not, because comments have been added to it.
We have created a window of type dialog by providing predefined constant WC_DIALOG as second argument of the function CreateWindowEx. WC_DIALOG is a predefined constant of type char array that holds the dialog box class name. Now, for creating button we pass second argument as "BUTTON". It is fairly simple, say you define a constant as #define WC_BUTTON "BUTTON" and then pass second argument WC_BUTTON to CreateWindowEx function, it will create a button, so instead of getting into mess keep in mind, that 2nd argument is the class name in textual presentation, and is different for several type of controls and windows. Now, as in 4th argument (that is style of the window being created) we basically have passed two styles, 1. WS_VISIBLE - means the window being created (regardless of its type) will be visible by default. 2. WS_OVERLAPPEDWINDOW - means the style to use for main windows, a window with titlebar and icon and minimize, maximize, and close button in title. This is the style you might have noticed in most of windows applications. So we write 'WS_OVERLAPPEDWINDOW | WS_VISIBLE', the sign between these two styles is '|' the bitwise or operator, that allows us to combine more than one styles for a window. Let us create some controls over our dialog that we created in last program. Few important things you need to know first. You may say window has handle that is used to refer to that window for sending messages or obtaining information from. The window handle is of type HWND that is already defined. So how to obtain handle of the dialog we created in last program? very simple, function CreateWindowEx returns the handle to the window that it creates. Why is it important to obtain handle of dialog at this stage? Yes, it is important because without a handle we will not be able to create any child windows over it (i.e. controls), or send messages to it. So to have simple we will write:
Now when we have obtained handle of the dialog we can easily create controls over it, lets say we create a button over it now. We will use same CreateWindowEx function for creating all kind of controls. The 9th argument of function CreateWindowEx is the parent window handle. So our final code becomes.
Just for testing purpose, change the button type name "BUTTON" to "EDIT" and recompile and run the program, you will notice there is an text box control that allows you editing of text. In this example we had 2 new styles 1. WS_CHILD - that means our button is child of the parent window, which actually is necessary because even through we have passed parent window handle, without this style our button may float independently outside of the dialog surface. Using this style we can make any kind of window a true child of the parent / draw on parent window's surface. 2. BS_PUSHBUTTON - is the style specific to the push buttons Now question is when we already have supplied class name "BUTTON", then why do we need to specify BS_PUSHBUTTON style? Because Radio buttons, Check boxes and Group boxes are also lay under same class, and we have to differentiate between them by supplying appropriate style. Up to here we gone through good enough, we created a main window, and successfully created a button over it's surface. Few things more to know before we start writing procedures to control the window events. a) Apart from a window's visual presentation, a window has some more attributes which we can get and set through the window handle, such as getting the old procedure attached to it, setting/attaching a new procedure, attaching some pointer to user defined data, and obtaining reference to it at certain point (what does this on earth means?), means you have some structure that holds data of one employee, and you wish to create 5 separate windows for 5 separate employees, so you set the user data to a pointer to that structure that holds the information. Our concern for now, is to attach a procedure to the window so we will go with it rightnow. Secondly, a window's visual structure is in a way that system draws some of its area and provides you some for drawing and creating controls over it. The area we can use, is called Client Area of the window, and the area which system draws automatically, is called Non-client Area. Besides, we can also draw in non-client area, but that comes in advanced topics. Client area is shown in the following figure:
The greenish part is the client area, we can use for drawing child controls, rest of the area (including borders, titlebar, minimize, maximize, close button) is non-client area. What is a window procedure? A normal function with 4 (four) arguments and return type, which receives every event that occurs on the window in response to user actions. e.g. that might be a left mouse button click on the surface of the window, or when user is rolling mouse over the surface of window, or the window is being resized, minimized, maximized, restored by the user, or even when a close button is clicked. When you work with pure API, you have to control all the events, if you do not attach a procedure to last example we created, after running the example you try closing the window from it top-right close button, it will take no action, why? because this is a major action over window and this action has not already been defined in the procedure system has already attached to this window. So basically, we will be replacing the existing procedure to have more and more control over the window. Why am I calling it 'replacing'? because I already said, there is always a procedure attached to a window that is created (unless it is made from custom class that we will discuss later), but that does not take action on major events such as close button clicked. Let us attach a procedure to our dialog window we created in previous program: A. First of all you need to know an important thing, a window procedure is called by system (for sending message) when an event has occurred on window or system level, and window needs to be informed through a message. B. Secondly memorize the structure of a window procedure. A window procedure is a function that returns value of type 'LRESULT WINAPI', where LRESULT is basically long and WINAPI is define for __stdcall. So no problem if using the return type 'long __stdcall' or may be only 'long'. Every window procedure has 4 (four) arguments. First argument is of type HWND (a handle to window that is receiving message), 2nd argument is of type UINT used for type of message received, which is basically an 'unsigned int' you may use either. 3rd argument is of type WPARAM, which is basically 'WORD', and type 'WORD' is basically 'int' so you may use any - either WPARAM, WORD, or directly int. 4th argument - the last argument is of type LPARAM, which is basically 'long' so use desired, either LPARAM or long directly. A window procedure prototype will look: 1.something like this:
2.or clear one:
3.or even smaller:
I recommend you use the first one, because it is quite possible that you need to compile same source code for different versions of Microsoft Windows, and it is quite possible that #defines for types LRESULT, WINAPI, WPARAM, and LPARAM do change for specific operating system (keeping in view the Windows Vista, Windows CE etc). I have not gone through these in depth, so better is use standard. Why we displayed a message box in our last examples? because when a message box is created, it has its own loop, and it does not return control to parent window or any parent loop until it is not closed and destroyed (dialogs such as the message box with such behavior are called Modal dialogs). So basically we did not have any message queue in previous examples so we used message box to hold the main window visible unless the message box is closed. Also because all the windows are automatically destroyed when application exits. So let us take our last example, 1. remove messages box from it, 2. create and attach a procedure to it. For attaching procedure to our window we will use a new function SetWindowLong, that will change the procedure attribute of the window. And one more function PostQuitMessage that will inform main loop to break. btw, a window procedure must not always return 0 (zero), for now return 0, this will be explained in upcoming readings.
What we did is, created a window using class WC_DIALOG, then attached a procedure to it using SetWindowLong function. Then setup the main message loop. Then in the procedure named myProc we checked for one message only called WM_CLOSE. This is the message sent to procedure by system when user closes the window either by clicked close button or by pressing Alt+F4. After receiving this message we sent a quit message to our applciation's main loop, to do that we used function PostQuitMessage that directly alerts the loop to stop forwarding messages and break immediately. btw, WC_ is a prefix used for 'Window Class', and WM_ for 'Window Message'. So, making code smaller as possible by removing comments and extra lines our final program becomes:
What is difference between a Notification and a Message? Notification is a message or part of a message sent to a window by system on occurrence of an event e.g. when mouse cursor moving on a window the window will receive WM_MOUSEMOVE. In a bit different case when a button is clicked or when text in a textbox has been changed by user message received (by parent window) is WM_COMMAND but WPARAM and LPARAM parameters of the window procedure are different, in button's case the low-word value of WPARAM is the id of the control, and in text box case high-word value of WPARAM is the notification EN_CHANGE. In simple words, all are messages but the ones, which notify you of an event, call them notifications. So a notification is actually a message but all messages are not notifications. On other hand, where a window procedure is predefined by system and you are not attaching a new procedure to it, you mostly send messages to the window to manipulate it. Almost all of such messages have already been defined in windows SDK. win32_1.cpp:307:3,win32_2.cpp:914:4,win32_3.cpp:752:5,win32_4.cpp:919:6 |