You are on page 1of 38

WINAPI Windows is the most widely used operating system on personal computers.

The Winapi is the source code interface that is used to create windows applications. In order to create Windows applications, we must download the platform sdk. The sdk (software development kit) contains header files, libraries, samples, documentation and tools that use the Winapi to develop applications. The Windows API is created for C and C++ programming languages. It is the most direct way to create Windows applications. The Windows API has four basic components.

The base services provide access to the fundamental resources on Windows. These include file systems, devices, processes, threads, registry or error handling. The GDI (Graphics Device Interface) is an interface for working with graphics. It is used to interact with graphic devices such as monitor, printer or a file. The User Interface provides functionality to create windows and controls. The Network services provide access to the network capabilities of the Windows OS.

What Characters Does the Unicode Standard Include?


The Unicode Standard defines codes for characters used in all the major languages written today. Scripts include the European alphabetic scripts, Middle Eastern right-to-left scripts, and many scripts of Asia. The Unicode Standard further includes punctuation marks, diacritics, mathematical symbols, technical symbols, arrows, dingbats, emoji, etc. It provides codes for diacritics, which are modifying character marks such as the tilde (~), that are used in conjunction with base characters to represent accented letters (, for example). In all, the Unicode Standard, Version 6.0 provides codes for 109,449 characters from the world's alphabets, ideograph sets, and symbol collections.

Fundamentally, computers just deal with numbers. They store letters and other characters by assigning a number for each one. Before Unicode was invented, there were hundreds of different encoding systems for assigning these numbers. No single encoding could contain enough characters: for example, the European Union alone requires several different encodings to cover all its languages. Even for a single language like English no single encoding was adequate for all the letters, punctuation, and technical symbols in common use. These encoding systems also conflict with one another. That is, two encodings can use the same number for two different characters, or use different numbers for the same character. Any given computer (especially servers) needs to support many different encodings; yet whenever data is passed between different encodings or platforms, that data always runs the risk of corruption.

Unicode is changing all that!


Unicode provides a unique number for every character, no matter what the platform, no matter what the program, no matter what the language.

Program instance definition An instance of a program is a copy of an executable version of the program that has been written to the computer's memory. A program is a sequence of instructions that indicates which operations the computer should perform on a set of data. An executable version of a program, also called an executable program, is a version of a program that is understandable by a computer's central processing unit (CPU) and that is ready to run as soon as it is copied from storage (usually a hard disk drive) into memory. (This contrasts with the source code version of a program, which is the version as originally written by humans using a programming language, and before it has been translated by a specialized program called a compiler into object code.) The CPU is the main logic unit of a computer. An instance of a program is typically created by a user clicking on an icon (i.e., small image) on a GUI (graphical user interface) or by entering a command at the command line and then pressing the ENTER key. Instances of programs can also be created by other programs. Multitasking, which allows multiple programs to run seemingly simultaneously on the same computer, also allows multiple instances of a single program to run simultaneously, if the program allows it. However, sometimes it is desired that there be only a single instance of a program on a computer, and programming languages provide techniques that can be used to enforce this. An example of a situation in which it can be useful to run multiple instances of a single program is having several multiple Nautilus (i.e., the official file manager for the Gnome desktop in

Linux) windows open simultaneously in order to compare the contents of different directories. Another example is a remote server from which multiple users are accessing a single program. Each instance of a program is, by definition, a separate process, as a process is merely an instance of a program, and thus each instance has a unique PID (process identification number). The number of instances of a program existing on a computer at the current time can be easily confirmed with commands such as ps and pstree, which show processes and their PIDs. Finding all of the instances of a program can be useful in some situations, particularly when the program crashes (i.e., freezes or stops operating as expected) and thus needs to be terminated. The word instance also has other meanings in a computer context, and these are likewise consistent with its broader definition as one particular incarnation of an object or situation. For example, in object-oriented programming (e.g., Java and C++) every object is an instance of some class and it is created by instantiating a class. In Java programs, an instance of a class is created using the new operator followed by the class name. For example, an object called my cat or felix could be created as an instance of the class cat. Perhaps the best way to summarize the difference between programs and instances of them is the statement that programs reside on disk and instances reside in memory. An executable file, also called an executable or a binary, is the ready-to-run (i.e., executable) form of a program. A program is a sequence of instructions understandable by a computer's CPU (central processing unit) that indicates which operations the computer should perform on a set of data. A file is a named collection of related data that appears to the user as a single, contiguous block of data and that is retained in storage. Storage refers to computer devices or media which can retain data for relatively long periods of time (e.g., years or decades), such as disk drives and magnetic tape. This contrasts with memory, which which retains its contents only briefly and which physically consists of RAM (random access memory) chips. Executable files consist of instructions that have been translated from their original source code into machine code, also called machine language or object code through the use of a specialized program called a compiler so that the CPU can use them directly and without further translation. Machine code consists entirely of zeros and ones, which represent the off and on states of the CPU logic circuits and memory cells. The object code files and any other necessary files (e.g., library files) are then linked together using a linker to create the executable. Linkers are generally included in compilers, and the linking is performed automatically. Executable files are usually stored in one of several standard directories on the hard disk drive (HDD) on Unix-like operating systems, including /bin, /sbin, /usr/bin, /usr/sbin and /usr/local/bin. Although it is not necessary for them to be in these locations in order to be

operable, it is often more convenient. When a program is launched, its executable file is copied into memory by the operating system so that its machine code will be immediately available to the CPU. In operating systems in which the type of file is indicated by appending an extension after its name, executables are indicated by extensions such as .exe, .com or .bin. Such extensions are generally not necessary in Unix-like operating systems.

Handle
A handle can be anything from an integer index to a pointer to a resource in kernel space. The idea is that they provide an abstraction of a resource, so you don't need to know much about the resource itself to use it. For instance, the HWND in the Win32 API is a handle for a Window. By itself it's useless: you can't glean any information from it. But pass it to the right API functions, and you can perform a wealth of different tricks with it. Internally you can think of the HWND as just an index into the GUI's table of windows (which may not necessarily be how it's implemented, but it makes the magic make sense).
A handle is most definitely not an int on Windows. Windows doesn't use signed (ie, int) values for handles. A handle on a 64-bit version of Windows will be a 64-bit unsigned value, whereas upon 32-bit versions, it will be 32-bits unsigned. As far as an app is concerned, a Win32 handle is just a void *. In a nutshell, a Win32 handle is (typically) a pointer to a struct that Windows doesn't want you to directly manipulate. It's a struct that is meant to be passed to, and manipulated by, only operating system functions. For example, you call CreateWindow() and it returns a handle to a window. Your app refers to it as an HWND, which is typedef'ed to a void * in Windows.h for the benefit of apps. A pointer to what? You don't know. Only the Windows operating system knows. It's a "window struct". What's that? You don't know. What members are in this struct? You don't know. Only the operating system knows. What do you do with this handle? You don't do anything at all with it, except to pass it to a great many other operating system functions that require you to pass it, definitely know what it really is, what its members are, and directly read/write those members. What's the point of this? First of all, the operating system needs to allocate some sort of "window struct" (ie, memory area) to store your own app's settings. After all, you've got your own window, distinct from any other app's windows. Your own window has its own distinct width and height, and title bar text, and lots of other settings that are unique to your own window. There has to be somewhere to store these personal "window settings" of yours. So the windows operating system allocates this "window struct" to store your own window settings. Then, the operating system (ie, CreateWindow) returns a pointer to this struct. It's telling you "Save this pointer to something. Don't you dare directly access its contents. I'm not going to even tell you what is in this struct. Just save this pointer somewhere.

Then when you call some other OS function, such as SetWindowText to change your window's title bar text, pass this pointer to SetWindowText, and I, the operating system, can know which window we're talking about, and I can change whatever member stores the title bar text of your window". The other point of this is that: If in a future version of Windows, Microsoft decides they need to change the layout of this "window struct", it won't break older apps. After all, your program never actually touches the members of this struct. So what do you care if, tomorrow someone runs your app on a new version of Windows that redefines the contents of that window struct. You never touch its contents. All you do is pass it around to different OS functions. What concern is it of yours that now, every single OS function you pass this pointer to, is operating upon a slightly different "window struct" than those functions were yesterday? An HINSTANCE is really a pointer to an "instance struct". What are its members? Only Microsoft knows. All we know is that it has something to do with storing settings about your EXE. An HWND is really a pointer to a "window struct". Only MS knows what it really is. All we know is that it's something to do with storing settings about a particular window. An HFONT is a pointer to a "font struct". Only MS knows what it really is. All we know is that it's something to do with storing settings about a particular font. Etc. As far as you're concerned, they are all a void *. Hell, you could typedef HSOMETHING to be a void *, and call them all an HSOMETHING. So why didn't MS do that, instead of having hundreds of these H...whatevers? Because then you'd really get confused. You don't want to mistakenly pass that "font struct" (HFONT) to SetWindowText (in lieu of a pointer to a "window struct"). And you don't want to mistakenly pass a HWND to GetModuleFilename() (in lieu of passing a pointer to an "instance struct"). So think of all these H...whatever as MS's way of helping you distinguish these various pointers, without giving you any more information about them than you need -- specifically, not any information about the actual content of these structs.

Windows Programming/Handles and Data Types


< Windows Programming

One of the first things that is going to strike many first-time programmers of the Win32 API is that there are tons and tons of old data types to deal with. Sometimes, just keeping all the correct data types in order can be more difficult than writing a nice program. This page will talk a little bit about some of the data types that a programmer will come in contact with.

[edit] Hungarian Notation


First, let's make a quick note about the naming convention used for some data types, and some variables. The Win32 API uses the so-called "Hungarian Notation" for naming variables. Hungarian Notation requires that a variable be prefixed with an abbreviation of its data type, so that when you are reading the code, you know exactly what type of variable it is. The reason this practice is done in the Win32 API is because there are many different data types, making it difficult to keep them all straight. Also, there are a number of different data types that are essentially defined the same way, and therefore some compilers will not pick up on errors when they are used incorrectly. As we discuss each data type, we will also note the common prefixes for that data type. Putting the letter "P" in front of a data type, or "p" in front of a variable usually indicates that the variable is a pointer. The letters "LP" or the prefix "lp" stands for "Long Pointer", which is exactly the same as a regular pointer on 32 bit machines. LP data objects are simply legacy objects that were carried over from Windows 3.1 or later, when pointers and long pointers needed to be differentiated. On modern 32-bit systems, these prefixes can be used interchangeably.

[edit] LPVOID
LPVOID data types are defined as being a "pointer to a void object". This may seem strange to some people, but the ANSI-C standard allows for generic pointers to be defined as "void*" types. This means that LPVOID pointers can be used to point to different types of objects, without creating a compiler error. However, the burden is on the programmer to keep track of what type of object is being pointed to. Also, some Win32 API functions may have arguments labeled as "LPVOID lpReserved". These reserved data members should never be used in your program, because they either depend on functionality that hasn't yet been implemented by Microsoft, or else they are only used in certain applications. If you see a function with an "LPVOID lpReserved" argument, you must always pass a NULL value for that parameter - some functions will fail if you do not do so. LPVOID objects frequently do not have prefixes, although it is relatively common to prefix an LPVOID variable with the letter "p", as it is a pointer.

[edit] DWORD, WORD, BYTE


These data types are defined to be a specific length, regardless of the target platform. There is a certain amount of additional complexity in the header files to achieve this, but the result is code that is very well standardized, and very portable to different hardware platforms and different compilers. DWORDs (Double WORDs), the most commonly occurring of these data types, are defined always to be unsigned 32-bit quantities. On any machine, be it 16, 32, or 64 bits, a DWORD is

always 32 bits long. Because of this strict definition, DWORDS are very common and popular on 32-bit machines, but are less common on 16-bit and 64-bit machines. WORDs (Single WORDs) are defined strictly as unsigned 16-bit values, regardless of what machine you are programming on. BYTEs are defined strictly as being unsigned 8-bit values. QWORDs (Quad WORDs), although rare, are defined as being unsigned 64-bit quantities. Putting a "P" in front of any of these identifiers indicates that the variable is a pointer. putting two "P"s in front indicates it's a pointer to a pointer. These variables may be unprefixed, or they may use any of the prefixes common with DWORDs. Because of the differences in compilers, the definition of these data types may be different, but typically these definitions are used:
#include <stdint.h>

typedef typedef typedef typedef

uint8_t BYTE; uint16_t WORD; uint32_t DWORD; uint64_t QWORD;

Notice that these definitions are not the same in all compilers. It is a known issue that the GNU GCC compiler uses the long and short specifiers differently from the Microsoft C Compiler. For this reason, the windows header files typically will use conditional declarations for these data types, depending on the compiler being used. In this way, code can be more portable. As usual, we can define pointers to these types as:
#include <stdint.h>

typedef typedef typedef typedef typedef typedef typedef typedef

uint8_t * PBYTE; uint16_t * PWORD; uint32_t * PDWORD; uint64_t * PQWORD; uint8_t ** PPBYTE; uint16_t ** PPWORD; uint32_t ** PPDWORD; uint64_t ** PPQWORD;

DWORD variables are typically prefixed with "dw". Likewise, we have the following prefixes:
Data Type Prefix BYTE WORD "b" "w"

DWORD QWORD

"dw" "qw"

[edit] LONG, INT, SHORT, CHAR


These types are not defined to a specific length. It is left to the host machine to determine exactly how many bits each of these types has.
Types
typedef typedef typedef typedef typedef typedef typedef typedef long LONG; unsigned long ULONG; int INT; unsigned int UINT; short SHORT; unsigned short USHORT; char CHAR; unsigned char UCHAR;

LONG notation LONG variables are typically prefixed with an "l" (lower-case L). UINT notation UINT variables are typically prefixed with an "i" or a "ui" to indicate that it is an integer, and that it is unsigned. CHAR, UCHAR notation These variables are usually prefixed with a "c" or a "uc" respectively.

If the size of the variable doesn't matter, you can use some of these integer types. However, if you want to exactly specify the size of a variable, so that it has a certain number of bits, use the BYTE, WORD, DWORD, or QWORD identifiers, because their lengths are platformindependent and never change.

[edit] STR, LPSTR


STR data types are string data types, with storage already allocated. This data type is less common than the LPSTR. STR data types are used when the string is supposed to be treated as an immediate array, and not as a simple character pointer. The variable name prefix for a STR data type is "sz" because it's a zero-terminated string (ends with a null character).

Most programmers will not define a variable as a STR, opting instead to define it as a character array, because defining it as an array allows the size of the array to be set explicitly. Also, creating a large string on the stack can cause greatly undesirable stack-overflow problems. LPSTR stands for "Long Pointer to a STR", and is essentially defined as such:
#define STR * LPSTR;

LPSTR can be used exactly like other string objects, except that LPSTR is explicitly defined as being ASCII, not unicode, and this definition will hold on all platforms. LPSTR variables will usually be prefixed with the letters "lpsz" to denote a "Long Pointer to a String that is Zeroterminated". The "sz" part of the prefix is important, because some strings in the Windows world (especially when talking about the DDK) are not zero-terminated. LPSTR data types, and variables prefixed with the "lpsz" prefix can all be used seamlessly with the standard library <string.h> functions.

[edit] TCHAR
TCHAR data types, as will be explained in the section on Unicode, are generic character data types. TCHAR can hold either standard 1-byte ASCII characters, or wide 2-byte Unicode characters. Because this data type is defined by a macro and is not set in stone, only character data should be used with this type. TCHAR is defined in a manner similar to the following (although it may be different for different compilers):
#ifdef UNICODE #define TCHAR WORD #else #define TCHAR BYTE #endif

[edit] TSTR, LPTSTR


Strings of TCHARs are typically referred to as TSTR data types. More commonly, they are defined as LPTSTR types as such:
#define TCHAR * LPTSTR

These strings can be either UNICODE or ASCII, depending on the status of the UNICODE macro. LPTSTR data types are long pointers to generic strings, and may contain either ASCII strings or Unicode strings, depending on the environment being used. LPTSTR data types are also prefixed with the letters "lpsz".

[edit] HANDLE
HANDLE data types are some of the most important data objects in Win32 programming, and also some of the hardest for new programmers to understand. Inside the kernel, Windows

maintains a table of all the different objects that the kernel is responsible for. Windows, buttons, icons, mouse pointers, menus, and so on, all get an entry in the table, and each entry is assigned a unique identifier known as a HANDLE. If you want to pick a particular entry out of that table, you need to give Windows the HANDLE value, and Windows will return the corresponding table entry. HANDLEs are defined as being unsigned 32-bit quantities in <windows.h>, but HANDLEs should never be used like integers. They are unique identifiers, and if you edit them, or use them in arithmetic, then they can never be used to get the table entry that they correspond to. In other words, HANDLEs should be stored, but they should never be changed by the programmer. HANDLEs are generally prefixed with an "h". Below are a few special handles that are worth discussing: A handle is actually a pointer to a pointer to a memory location.Handles are unsigned integers that Windows uses internally to keep track of objects in memory. Windows moves objects like memory blocks in memory to make room, if the object is moved in memory, the handles table is updated.

[edit] HWND
HWND data types are "Handles to a Window", and are used to keep track of the various objects that appear on the screen. To communicate with a particular window, you need to have a copy of the window's handle. HWND variables are usually prefixed with the letters "hwnd", just so the programmer knows they are important. Canonically, main windows are defined as:
HWND hwnd;

Child windows are defined as:


HWND hwndChild1, hwndChild2...

and Dialog Box handles are defined as:


HWND hDlg;

Although you are free to name these variables whatever you want in your own program, readability and compatibility suffer when an idiosyncratic naming scheme is chosen - or worse, no scheme at all.

[edit] HINSTANCE
HINSTANCE variables are handles to a program instance. Each program gets a single instance variable, and this is important so that the kernel can communicate with the program. If you want to create a new window, for instance, you need to pass your program's HINSTANCE variable to the kernel, so that the kernel knows where the new window belongs to. If you want to communicate with another program, it is frequently very useful to have a copy of that program's

instance handle. HINSTANCE variables are usually prefixed with an "h", and furthermore, since there is frequently only one HINSTANCE variable in a program, it is canonical to declare that variable as such:
HINSTANCE hInstance;

It is usually a benefit to make this HINSTANCE variable a global value, so that all your functions can access it when needed.

[edit] HMENU
If your program has a drop-down menu available (as most visual Windows programs do), that menu will have an HMENU handle associated with it. To display the menu, or to alter its contents, you need to have access to this HMENU handle. HMENU handles are frequently prefixed with simply an "h".

[edit] WPARAM, LPARAM


In the earlier days of Microsoft Windows, parameters were passed to a window in one of two formats: WORD-length (16-bit) parameters, and LONG-length (32-bit) parameters. These parameter types were defined as being WPARAM (16-bit) and LPARAM (32-bit). However, in modern 32-bit systems, WPARAM and LPARAM are both 32 bits long. The names however have not changed, for legacy reasons. WPARAM and LPARAM variables are generic function parameters, and are frequently type-cast to other data types including pointers and DWORDs.

The Main Window Class


There are two primary things you must do in order to create even the simplest window: you must create the central point of the program, and you must tell the operating system how to respond when the user does what. Just like a C++ program always has a main() function, a Win32 program needs a central function call WinMain. The syntax of that function is: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ); Unlike the C++ main() function, the arguments of the WinMain() function are not optional. Your program will need them to communicate with the operating system. The first argument, hInstance, is a handle to the instance of the program you are writing. The second argument, hPrevInstance, is used if your program had any previous instance. If not, this argument can be ignored, which will always be the case. The third argument, lpCmdLine, is a string that represents all items used on the command line to compile the application.

The last argument, nCmdShow, controls how the window you are building will be displayed. An object that displays on your screen is called a window. Because there can be various types of windows in your programs, your first responsibility is to control them, know where they are, what they are doing, why, and when. The first control you must exercise on these different windows is to host them so that all windows of your program belong to an entity called the main window. This main window is created using an object that can be called a class (strictly, a structure). The Win32 library provides two classes for creating the main window and you can use any one of them. They are WNDCLASS and WNDCLASSEX. The second adds only a slight feature to the first. Therefore, we will mostly use the WNDCLASSEX structure for our lessons. The WNDCLASS and the WNDCLASSEX classes are defined as follows: typedef struct _WNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; } WNDCLASS, *PW typedef struct _WNDCLASSEX { UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; } WNDCLASSEX, *PWNDCLASSEX;

To create a window, you must "fill out" this class, which means you must provide a value for each of its members so the operating system would know what your program is expected to do. The first thing you must do in order to create an application is to declare a variable of either WNDCLASS or WNDCLASSEX type. Here is an example of a WNDCLASSEX variable: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; return 0; }

The Size of the Window Class


After declaring a WNDCLASSEX variable, you must specify its size. This is done by initializing your variable with the sizeof operator applied to the window class as follows: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

WNDCLASSEX WndClsEx; WndClsEx.cbSize = sizeof(WNDCLASSEX); return 0; }

Additional Memory Request


Upon declaring a WNDCLASSEX variable, the compiler allocates an amount of memory space for it, as it does for all other variables. If you think you will need more memory than allocated, assign the number of extra bytes to the cbClsExtra member variable. Otherwise, the compiler initializes this variable to 0. If you do not need extra memory for your WNDCLASSEX variable, initialize this member with 0. Otherwise, you can do it as follows: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; WndClsEx.cbSize = sizeof(WNDCLASSEX); WndClsEx.cbClsExtra = 0; return 0; }

The Application's Instance


Creating an application is equivalent to creating an instance for it. To communicate to the WinMain() function that you want to create an instance for your application, which is, to make it available as a resource, assign the WinMain()'s hInstance argument to your WNDCLASS variable: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; WndClsEx.cbSize = sizeof(WNDCLASSEX); WndClsEx.cbClsExtra = 0; WndClsEx.hInstance = hInstance; return 0; }

Window Extra-Memory
When an application has been launched and is displaying on the screen, which means an instance of the application has been created, the operating system allocates an amount of memory space for that application to use. If you think that your application's instance will need more memory than that, you can request that extra memory bytes be allocated to it. Otherwise, you can let the operating system handle this instance memory issue and initialize the cbWndExtra member variable to 0: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

WNDCLASSEX WndClsEx; WndClsEx.cbSize WndClsEx.cbClsExtra WndClsEx.cbWndExtra WndClsEx.hInstance return 0; } = = = = sizeof(WNDCLASSEX); 0; 0; hInstance;

The Main Window's Style


The style member variable specifies the primary operations applied on the window class. The actual available styles are constant values. For example, if a user moves a window or changes its size, you would need the window to be redrawn to get its previous characteristics. To redraw the window horizontally, you would apply the CS_HREDRAW. In the same way, to redraw the window vertically, you can apply the CS_VREDRAW. The styles are combined using the bitwise OR (|) operator. The CS_HREDRAW and the CS_VREDRAW styles can be combined and assigned to the style member variable as follows: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; WndClsEx.cbSize WndClsEx.style WndClsEx.cbClsExtra WndClsEx.cbWndExtra WndClsEx.hInstance return 0; } = = = = = sizeof(WNDCLASSEX); CS_HREDRAW | CS_VREDRAW; 0; 0; hInstance;

What is a Message?
A message is an integer value. If you look up in your header files (which is good and common practice when investigating the workings of API's) you can find things like:
#define WM_INITDIALOG #define WM_COMMAND #define WM_LBUTTONDOWN 0x0110 0x0111 0x0201

...and so on. Messages are used to communicate pretty much everything in windows at least on basic levels. If you want a window or control (which is just a specialized window) to do something you send it a message. If another window wants you to do something it sends you a message. If an event happens such as the user typing on the keyboard, moving the mouse, clicking a button, then messages are sent by the system to the windows affected. If you are one of those windows, you handle the message and act accordingly.

Each windows message may have up to two parameters, wParam and lParam. Originally wParam was 16 bit and lParam was 32 bit, but in Win32 they are both 32 bit. Not every message uses these parameters, and each message uses them differently. For example the WM_CLOSE message doesn't use either, and you should ignore them both. The WM_COMMAND message uses both, wParam contains two values, HIWORD(wParam) is the notification message (if applicable) and LOWORD(wParam) is the control or menu id that sent the message. lParam is the HWND (window handle) to the control which sent the message or NULL if the messages isn't from a control. and LOWORD() are macros defined by windows that single out the two high bytes (High Word) of a 32 bit value (0xFFFF0000) and the low word (0x0000FFFF) respectively. In Win32 a WORD is a 16bit value, making DWORD (or Double Word) a 32bit value.
HIWORD()

To send a message you can use PostMessage() or SendMessage(). PostMessage() puts the message into the Message Queue and returns immediatly. That means once the call to PostMessage() is done the message may or may not have been processed yet. SendMessage() sends the message directly to the window and does not return untill the window has finished processing it. If we wanted to close a window we could send it a WM_CLOSE message like this PostMessage(hwnd, WM_CLOSE, 0, 0); which would have the same effect as clicking on the button on the top of the window. Notice that wParam and lParam are both 0. This is because, as mentioned, they aren't used for WM_CLOSE.

What is the Message Queue


Lets say you were busy handling the WM_PAINT message and suddenly the user types a bunch of stuff on the keyboard. What should happen? Should you be interrupted in your drawing to handle the keys or should the keys just be discarded? Wrong! Obviously neither of these options is reasonable, so we have the message queue, when messages are posted they are added to the message queue and when you handle them they are removed. This ensure that you aren't going to miss messages, if you are handling one, the others will be queued up untill you get to them.

What is a Message Loop


while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); }

1. The message loop calls GetMessage(), which looks in your message queue. If the message queue is empty your program basically stops and waits for one (it Blocks). 2. When an event occures causing a message to be added to the queue (for example the system registers a mouse click) GetMessages() returns a positive value indicating there is a message to be processed, and that it has filled in the members of the MSG structure we passed it. It returns 0 if it hits WM_QUIT, and a negative value if an error occured. 3. We take the message (in the Msg variable) and pass it to TranslateMessage(), this does a bit of additional processing, translating virtual key messages into character messages. This step is actually optional, but certain things won't work if it's not there. 4. Once that's done we pass the message to DispatchMessage(). What DispatchMessage() does is take the message, checks which window it is for and then looks up the Window Procedure for the window. It then calls that procedure, sending as parameters the handle of the window, the message, and wParam and lParam. 5. In your window procedure you check the message and it's parameters, and do whatever you want with them! If you aren't handling the specific message, you almost always call DefWindowProc() which will perform the default actions for you (which often means it does nothing). 6. Once you have finished processing the message, your windows procedure returns, DispatchMessage() returns, and we go back to the beginning of the loop. This is a very important concept for windows programs. Your window procedure is not magically called by the system, in effect you call it yourself indirectly by calling DispatchMessage(). If you wanted, you could use GetWindowLong() on the window handle that the message is destined for to look up the window's procedure and call it directly!
while(GetMessage(&Msg, NULL, 0, 0) > 0) { WNDPROC fWndProc = (WNDPROC)GetWindowLong(Msg.hwnd, GWL_WNDPROC); fWndProc(Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam); }

I tried this with the previous example code, and it does work, however there are various issues such as Unicode/ANSI translation, calling timer callbacks and so forth that this method will not account for, and very likely will break all but trivial applications. So do it to try it, but don't do it in real code :) Notice that we use GetWindowLong() to retreive the window procedure associated with the window. Why don't we just call our WndProc() directly?

Well our message loop is responsible for ALL of the windows in our program, this includes things like buttons and list boxes that have their own window procedures, so we need to make sure that we call the right procedure for the window. Since more than one window can use the same window procedure, the first parameter (the handle to the window) is used to tell the window procedure which window the message is intended for. As you can see, your application spends the majority of it's time spinning round and round in this message loop, where you joyfully send out messages to the happy windows that will process them. But what do you do when you want your program to exit? Since we're using a while() loop, if GetMessage() were to return FALSE (aka 0), the loop would end and we would reach the end of our WinMain() thus exiting the program. This is exactly what PostQuitMessage() accomplishes. It places a WM_QUIT message into the queue, and instead of returning a positive value, GetMessage() fills in the Msg structure and returns 0. At this point, the wParam member of Msg contains the value that you passed to PostQuitMessage() and you can either ignore it, or return it from WinMain() which will then be used as the exit code when the process terminates. IMPORTANT: GetMessage() will return -1 if it encounters an error. Make sure you remember this, or it will catch you out at some point... even though GetMessage() is defined as returning a BOOL, it can return values other than TRUE or FALSE, since BOOL is defined as UINT (unsigned int). The following are examples of code that may seem to work, but will not process certian conditions correctly:
while(GetMessage(&Msg, NULL, 0, 0)) while(GetMessage(&Msg, NULL, 0, 0) != 0) while(GetMessage(&Msg, NULL, 0, 0) == TRUE)

The above are all wrong! It may be of note that I used to use the first of these throughout the tutorial, since as I just mentioned, it works fine as long as GetMessage() never fails, which when your code is correct it won't. However I failed to take into consideration that if you're reading this, your code probably won't be correct a lot of the time, and GetMessage() will fail at some point :) I've gone through and corrected this, but forgive me if I've missed a few spots.
while(GetMessage(&Msg, NULL, 0, 0) > 0)

This, or code that has the same effect should always be used.

The Message Loop


This is the heart of the whole program, pretty much everything that your program does passes through this point of control. We receive messages from

the message queue using the GetMessage() function and dispatch them to the window procedure using the DispatchMessage() call.
while(GetMessage(&Msg, NULL, 0, 0)>0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam;

gets a message from your application's message queue. Any time the user moves the mouse, types on the keyboard, clicks on your window's menu, or does any number of other things, messages are generated by the system and entered into your program's message queue. By calling GetMessage() you are requesting the next available message to be removed from the queue and returned to you for processing. If there is no message, GetMessage() Blocks. If you are unfamiliar with the term, it means that it waits untill there is a message, and then returns it to you.
GetMessage()

does some additional processing on keyboard events like generating WM_CHAR messages to go along with WM_KEYDOWN messages. Finally DispatchMessage() sends the message out to the window that the message was sent to. This could be our main window or it could be another one, or a control, and in some cases a window that was created behind the scenes by the sytem or another program. This isn't something you need to worry about because all we are concerned with is that we get the message and send it out, the system takes care of the rest making sure it gets to the proper window.
TranslateMessage()

Step 4: the Window Procedure


If the message loop is the heart of the program, the window procedure is the brain. This is where all the messages that are sent to our window get processed.

This function is declared with a return type of LRESULT CALLBACK. The LRESULT type is used by Windows to declare a long integer, and CALLBACK is a calling convention used with functions that are called by Windows. The Windows Procedure is a function pointer, which allows you to call it whatever you

want because the function's address will be assigned as a function pointer upon creation of the window class. hwnd - Only important if you have several windows of the same class open at one time. This is used to determine which window hwnd pointed to before deciding on an action. message - The actual message identifier that WndProc will be handling. wParam(word-length parameter) and lParam(long length parameter) Extensions of the message parameter. Used to give more information and point to specifics that message cannot on its own. Message parameters often contain information in both their low-order and high-order words. There are several macros an application can use to extract information from the message parameters. The LOWORD macro, for example, extracts the low-order word (bits 0 through 15) from a message parameter. Other macros include HIWORD, LOBYTE, and HIBYTE. Message Processing
The name of the window procedure we reviewed in the previous lesson must be assigned to the lpfnWndProc member variable of the WNDCLASS or WNDCLASSEX variable. This can be defined as follows: #include <windows.h> LRESULT WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; WndClsEx.cbSize WndClsEx.style WndClsEx.lpfnWndProc WndClsEx.cbClsExtra WndClsEx.cbWndExtra WndClsEx.hInstance return 0; } LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch(Msg) { case WM_CLOSE: = = = = = = sizeof(WNDCLASSEX); CS_HREDRAW | CS_VREDRAW; WndProcedure; 0; 0; hInstance;

DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(WM_QUIT); break; default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; }

The window procedure is called for each message, the HWND parameter is the handle of your window, the one that the message applies to. This is important since you might have two or more windows of the same class and they will use the same window procedure (WndProc()). The difference is that the parameter hwnd will be different depending on which window it is. For example when we get the WM_CLOSE message we destroy the window. Since we use the window handle that we received as the first paramter, any other windows will not be affected, only the one that the message was intended for. is sent when the user presses the Close Button or types Alt-F4. This will cause the window to be destroyed by default, but I like to handle it explicitly, since this is the perfect spot to do cleanup checks, or ask the user to save files etc. before exiting the program. Destroys the specified window.
WM_CLOSE

The function sends WM_DESTROY and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus from it. The function also destroys the window's menu, flushes the thread message queue, destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if the window is at the top of the viewer chain).If the specified window is a parent or owner window, DestroyWindow automatically destroys the associated child or owned windows when it destroys the parent or owner window. The function first destroys child or owned windows, and then it destroys the parent or owner window. DestroyWindow also destroys modeless dialog boxes created by the CreateDialog function. PostQuitMessage().The application exit code. This value is used as the wParam
parameter of the WM_QUIT message.This function does not return a value. The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately; the function simply indicates to the system that the thread is requesting to quit at some time in the future.

When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the system. The exit value returned to the system must be the wParam parameter of the WM_QUIT message. This posts the WM_QUIT message to the message loop. We never receive this message, because it causes GetMessage() to return FALSE, and as you'll see in our message loop code, when that happens we stop processing messages and return the final result code, the wParam of WM_QUIT which happens to be the value we passed into PostQuitMessage(). The return value is only really useful if your program is designed to be called by another program and you want to return a specific value. This function uses a switch control to list all necessary messages and process each one in turn. This processes only the messages that you ask it to. If you have left-over messages, and you will always have un-processed messages, you can call the DefWindowProc() function at the end to take over. The most basic message you can process is to make sure a user can close a window after using it. This can be done with a function called PostQuitMessage(). Its syntax is: VOID PostQuitMessage(int nExitCode) This function takes one argument which is the value of the LPARAM argument. To close a window, you can pass the argument as WM_QUIT.

The Application Main Icon


An icon can be used to represent an application in My Computer or Windows Explorer. To assign this small picture to your application, you can either use an existing icon or design your own. To make your programming a little faster, Microsoft Windows installs a few icons. The icon is assigned to the hIcon member variable using the LoadIcon() function. For a Win32 application, the syntax of this function is: HICON LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName); The hInstance argument is a handle to the file in which the icon was created. This file is usually stored in a library (DLL) of an executable program. If the icon was created as part of your application, you can use the hInstance of your application. If your are using one of the icons below, set this argument to NULL. The lpIconName is the name of the icon to be loaded. This name is added to the resource file when you create the icon resource. It is added automatically if you add the icon as part of your resources; otherwise you can add it manually when creating your resource script. Normally, if you had created and designed an icon and gave it an identifier, you can pass it using the MAKEINTRESOURCE macro. To make your programming a little faster, Microsoft Windows installs a few icons you can use

for your application. These icons have identification names that you can pass to the LoadIcon() function as the lpIconName argument. The icons are: ID IDI_APPLICATION IDI_INFORMATION IDI_ASTERISK IDI_QUESTION IDI_WARNING IDI_EXCLAMATION IDI_HAND IDI_ERROR If you designed your own icon (you should make sure you design a 32x32 and a 16x16 versions, even for convenience), to use it, specify the hInstance argument of the LoadIcon() function to the instance of your application. Then use the MAKEINTRESOURCE macro to convert its identifier to a null-terminated string. This can be done as follows: WndCls.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_STAPLE)); The icon can be specified by its name, which would be a null-terminated string passed as lpszResourceName. If you had designed your icon and gave it an ID, you can pass this identifier to the LoadIcon() method. The LoadIcon() member function returns an HICON object that you can assign to the hIcon member variable of your WNDCLASS object. Besides the regular (32x32) icon, the WNDCLASSEX structure allows you to specify a small icon (16x16) to use in some circumstances. You can specify both icons as follows: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; WndClsEx.cbSize WndClsEx.style WndClsEx.lpfnWndProc WndClsEx.cbClsExtra WndClsEx.cbWndExtra WndClsEx.hIcon WndClsEx.hInstance WndClsEx.hIconSm return 0; } = = = = = = = = sizeof(WNDCLASSEX); CS_HREDRAW | CS_VREDRAW; WndProcedure; 0; 0; LoadIcon(NULL, IDI_APPLICATION); hInstance; LoadIcon(NULL, IDI_APPLICATION); Picture

Introduction to Cursors

A cursor is used to locate the position of the mouse pointer on a document or the screen. To use a cursor, call the Win32 LoadCursor() function. Its syntax is: HCURSOR LoadCursor(HINSTANCE hInstance, LPCTSTR lpCursorName); The hInstance argument is a handle to the file in which the cursor was created. This file is usually stored in a library (DLL) of an executable program. If the cursor was created as part of your application, you can use the hInstance of your application. If your are using one of the below cursors, set this argument to NULL. When Microsoft Windows installs, it also installs various standard cursors you can use in your program. Each one of these cursors is recognized by an ID which is simply a constant integers. The available cursors are: ID IDC_APPSTARTING IDC_ARROW IDC_CROSS IDC_HAND Picture Description Used to show that something undetermined is going on or the application is not stable This standard arrow is the most commonly used cursor The crosshair cursor is used in various circumstances such as drawing TheHand is standard only in Windows 2000. If you are using a previous operating system and need this cursor, you may have to create your own. The combined arrow and question mark cursor is used when providing help on a specific item on a window object The I-beam cursor is used on text-based object to show the position of the caret This cursor is not used anymore This cursor can be used to indicate an unstable situation This cursor is not used anymore The four arrow cursor pointing north, south, east, and west is highly used to indicate that an object is selected or that it is ready to be moved The northeast and southwest arrow cursor can be used when resizing an object on both the length and the height The north - south arrow pointing cursor can be used when shrinking or heightening an object The northwest - southeast arrow pointing cursor can be used when resizing an object on both the length and the height The west - east arrow pointing cursor can be used when narrowing or enlarging an object The vertical arrow cursor can be used to indicate the presence of the mouse or the caret The Hourglass cursor is usually used to indicate that a window or the application is not ready.

IDC_HELP IDC_IBEAM IDC_ICON IDC_NO IDC_SIZE IDC_SIZEALL

IDC_SIZENESW IDC_SIZENS IDC_SIZENWSE IDC_SIZEWE IDC_UPARROW IDC_WAIT

The LoadCursor() member function returns an HCURSOR value. You can assign it to the hCursor member variable of your WNDCLASS object. Here is an example: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; WndClsEx.cbSize WndClsEx.style WndClsEx.lpfnWndProc WndClsEx.cbClsExtra WndClsEx.cbWndExtra WndClsEx.hIcon WndClsEx.hCursor WndClsEx.hInstance WndClsEx.hIconSm return 0; } = = = = = = = = = sizeof(WNDCLASSEX); CS_HREDRAW | CS_VREDRAW; WndProcedure; 0; 0; LoadIcon(NULL, IDI_APPLICATION); LoadCursor(NULL, IDC_ARROW); hInstance; LoadIcon(NULL, IDI_APPLICATION);

The Window's Background Color


To paint the work area of the window, you must specify what color will be used to fill it. This color is created as an HBRUSH and assigned to the hbrBackground member variable of your WNDCLASS or WNDCLASSEX variable. The color you are using must be a valid HBRUSH or you can cast a known color to HBRUSH. The Win32 library defines a series of colors known as stock objects. To use one of these colors, call the GetStockObject() function. For example, to paint the windows background in black, you can pass the BLACK_BRUSH constant to the GetStockObject() function, cast it to HBRUSH and assign the result to hbrBackground. In addition to the stock objects, the Microsoft Windows provides a series of colors for its own internal use. These are the colors used to paint the borders of frames, buttons, scroll bars, title bars, text, etc. The colors are named (you should be able to predict their appearance or role from their name) COLOR_ACTIVEBORDER, COLOR_ACTIVECAPTION, COLOR_APPWORKSPACE, COLOR_BACKGROUND, COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNTEXT, COLOR_CAPTIONTEXT, COLOR_GRAYTEXT, COLOR_HIGHLIGHT, COLOR_HIGHLIGHTTEXT, COLOR_INACTIVEBORDER, COLOR_INACTIVECAPTION, COLOR_MENU, COLOR_MENUTEXT, COLOR_SCROLLBAR, COLOR_WINDOW, COLOR_WINDOWFRAME, and COLOR_WINDOWTEXT. You can use any of these colors to paint the background of your window. First cast it to HBRUSH and assign it to hbrBackground: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; WndClsEx.cbSize WndClsEx.style WndClsEx.lpfnWndProc WndClsEx.cbClsExtra WndClsEx.cbWndExtra WndClsEx.hIcon WndClsEx.hCursor = = = = = = = sizeof(WNDCLASSEX); CS_HREDRAW | CS_VREDRAW; WndProcedure; 0; 0; LoadIcon(NULL, IDI_APPLICATION); LoadCursor(NULL, IDC_ARROW);

WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); WndClsEx.hInstance = hInstance; WndClsEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return 0; }

The Application's Main Menu


If you want the window to display a menu, first create or design the resource menu (we will eventually learn how to do this). After creating the menu, assign its name to the lpszMenuName name to your WNDCLASS or WNDCLASSEX variable. Otherwise, pass this argument as NULL. Here is an example: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; WndClsEx.cbSize WndClsEx.style WndClsEx.lpfnWndProc WndClsEx.cbClsExtra WndClsEx.cbWndExtra WndClsEx.hIcon WndClsEx.hCursor WndClsEx.hbrBackground WndClsEx.lpszMenuName WndClsEx.hInstance WndClsEx.hIconSm return 0; } = = = = = = = = = = = sizeof(WNDCLASSEX); CS_HREDRAW | CS_VREDRAW; WndProcedure; 0; 0; LoadIcon(NULL, IDI_APPLICATION); LoadCursor(NULL, IDC_ARROW); (HBRUSH)GetStockObject(WHITE_BRUSH); NULL; hInstance; LoadIcon(NULL, IDI_APPLICATION);

The Window's Class Name


To create a window, you must provide its name as everything else in the computer has a name. The class name of your main window must be provided to the lpszClassName member variable of your WNDCLASS or WNDCLASSEX variable. You can provide the name to the variable or declare a global null-terminated string. Here is an example: LPCTSTR ClsName = L"BasicApp"; INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; WndClsEx.cbSize WndClsEx.style WndClsEx.lpfnWndProc WndClsEx.cbClsExtra WndClsEx.cbWndExtra WndClsEx.hIcon WndClsEx.hCursor WndClsEx.hbrBackground = = = = = = = = sizeof(WNDCLASSEX); CS_HREDRAW | CS_VREDRAW; WndProcedure; 0; 0; LoadIcon(NULL, IDI_APPLICATION); LoadCursor(NULL, IDC_ARROW); (HBRUSH)GetStockObject(WHITE_BRUSH);

WndClsEx.lpszMenuName WndClsEx.lpszClassName WndClsEx.hInstance WndClsEx.hIconSm return 0; }

= = = =

NULL; ClsName; hInstance; LoadIcon(NULL, IDI_APPLICATION);

Registerig window
Before we can create a window, we must register it within the Windows. All windows must be registered. Later on we will see, that we do not register a window, when we create a button, static text etc. This is because these controls are predefined. They have already been registered. Programming in C/winapi means a lot of working with structures. To register a window, we must create and fill an WNDCLASS structure. We set the window style, extra allocation bytes, window class name, handle of the program instance, background brush, optional menu name, window procedure, handle of the cursor and icon. Finally, we call the RegisterClass() function. you can register a class once, and create as many windows as you want from it, without having to specify all those attributes over and over. Most of the attributes you set in the window class can be changed on a per-window basis if desired

Window Registration
After initializing the window class, you must make it available to the other controls that will be part of your application. This process is referred to as registration. To register the window class, call the RegisterClass() for a WNDCLASS variable. If you created your window class using the WNDCLASSEX structure, call the RegisterClassEx() function. Their syntaxes are: ATOM RegisterClass(CONST WNDCLASS *lpWndClass); ATOM RegisterClassEx(CONST WNDCLASSEX *lpwcx); The function simply takes as argument a pointer to a WNDCLASS or WNDCLASSEX. This call can be done as follows: INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndClsEx; . . . RegisterClassEx(&WndClsEx); return 0; }

MESSAGEBOX Displays a modal dialog box that contains a system icon, a set of buttons, and a brief applicationspecific message, such as status or error information. The message box returns an integer value that indicates which button the user clicked.

Syntax
int WINAPI MessageBox( __in_opt HWND hWnd, __in_opt LPCTSTR lpText, __in_opt LPCTSTR lpCaption, __in UINT uType );

Parameters
hWnd [in, optional]

Type: HWND A handle to the owner window of the message box to be created. If this parameter is NULL, the message box has no owner window.
lpText [in, optional]

Type: LPCTSTR The message to be displayed. If the string consists of more than one line, you can separate the lines using a carriage return and/or linefeed character between each line.
lpCaption [in, optional]

Type: LPCTSTR The dialog box title. If this parameter is NULL, the default title is Error.
uType [in]

Type: UINT The contents and behavior of the dialog box. This parameter can be a combination of flags from the following groups of flags. To indicate the buttons displayed in the message box, specify one of the following values.

Value MB_ABORTRETRYIGNORE 0x00000002L

Meaning

The message box contains three push buttons: Abort, Retry, and Ignore.

MB_CANCELTRYCONTINUE The message box contains three push buttons: Cancel, Try 0x00000006L MB_HELP 0x00004000L MB_OK 0x00000000L MB_OKCANCEL 0x00000001L MB_RETRYCANCEL 0x00000005L MB_YESNO 0x00000004L MB_YESNOCANCEL 0x00000003L

Again, Continue. Use this message box type instead of MB_ABORTRETRYIGNORE. Adds a Help button to the message box. When the user clicks the Help button or presses F1, the system sends a WM_HELP message to the owner. The message box contains one push button: OK. This is the default.

The message box contains two push buttons: OK and Cancel.

The message box contains two push buttons: Retry and Cancel.

The message box contains two push buttons: Yes and No.

The message box contains three push buttons: Yes, No, and Cancel.

To display an icon in the message box, specify one of the following values.
Value MB_ICONEXCLAMATION 0x00000030L MB_ICONWARNING Meaning

An exclamation-point icon appears in the message box.

An exclamation-point icon appears in the message box.

0x00000030L MB_ICONINFORMATION 0x00000040L MB_ICONASTERISK 0x00000040L

An icon consisting of a lowercase letter i in a circle appears in the message box. An icon consisting of a lowercase letter i in a circle appears in the message box. A question-mark icon appears in the message box. The questionmark message icon is no longer recommended because it does not clearly represent a specific type of message and because the phrasing of a message as a question could apply to any message type. In addition, users can confuse the message symbol question mark with Help information. Therefore, do not use this question mark message symbol in your message boxes. The system continues to support its inclusion only for backward compatibility. A stop-sign icon appears in the message box.

MB_ICONQUESTION 0x00000020L

MB_ICONSTOP 0x00000010L MB_ICONERROR 0x00000010L MB_ICONHAND 0x00000010L

A stop-sign icon appears in the message box.

A stop-sign icon appears in the message box.

To indicate the default button, specify one of the following values.


Value Meaning

MB_DEFBUTTON1 The first button is the default button. 0x00000000L MB_DEFBUTTON2 0x00000100L

MB_DEFBUTTON1 is the default unless MB_DEFBUTTON2, MB_DEFBUTTON3, or MB_DEFBUTTON4 is specified. The second button is the default button.

MB_DEFBUTTON3 0x00000200L MB_DEFBUTTON4 0x00000300L

The third button is the default button.

The fourth button is the default button.

To indicate the modality of the dialog box, specify one of the following values.
Value Meaning

The user must respond to the message box before continuing work in the window identified by the hWnd parameter. However, the user can move to the windows of other threads and work in those windows.
MB_APPLMODAL 0x00000000L

Depending on the hierarchy of windows in the application, the user may be able to move to other windows within the thread. All child windows of the parent of the message box are automatically disabled, but pop-up windows are not.

MB_APPLMODAL is the default if neither MB_SYSTEMMODAL nor MB_TASKMODAL is specified. Same as MB_APPLMODAL except that the message box has the MB_SYSTEMMODAL WS_EX_TOPMOST style. Use system-modal message boxes to notify the user of serious, potentially damaging errors that require 0x00001000L immediate attention (for example, running out of memory). This flag has no effect on the user's ability to interact with windows other than those associated with hWnd. Same as MB_APPLMODAL except that all the top-level windows MB_TASKMODAL belonging to the current thread are disabled if the hWnd parameter is NULL. Use this flag when the calling application or library does not 0x00002000L have a window handle available but still needs to prevent input to other windows in the calling thread without suspending other threads.

To specify other options, use one or more of the following values.


Value Meaning

Same as desktop of the interactive window station. For


MB_DEFAULT_DESKTOP_ONLY more information, see Window Stations. 0x00020000L

If the current input desktop is not the default desktop, MessageBox does not return until the user switches to the default desktop. The text is right-justified.

MB_RIGHT 0x00080000L MB_RTLREADING 0x00100000L MB_SETFOREGROUND 0x00010000L MB_TOPMOST 0x00040000L

Displays message and caption text using right-to-left reading order on Hebrew and Arabic systems. The message box becomes the foreground window. Internally, the system calls the SetForegroundWindow function for the message box. The message box is created with the WS_EX_TOPMOST window style. The caller is a service notifying the user of an event. The function displays a message box on the current active desktop, even if there is no user logged on to the computer. Terminal Services: If the calling thread has an impersonation token, the function directs the message box to the session specified in the impersonation token. If this flag is set, the hWnd parameter must be NULL. This is so that the message box can appear on a desktop other than the desktop corresponding to the hWnd. For information on security considerations in regard to using this flag, see Interactive Services. In particular, be aware that this flag can produce interactive content on a locked desktop and should therefore be used for only a very limited set of scenarios, such as resource exhaustion.

MB_SERVICE_NOTIFICATION 0x00200000L

Return value
Type: int

If a message box has a Cancel button, the function returns the IDCANCEL value if either the ESC key is pressed or the Cancel button is selected. If the message box has no Cancel button, pressing ESC has no effect. If the function fails, the return value is zero. To get extended error information, call GetLastError. If the function succeeds, the return value is one of the following menu-item values.
Return code/value IDABORT 3 IDCANCEL 2 IDCONTINUE 11 IDIGNORE 5 IDNO 7 IDOK 1 IDRETRY 4 IDTRYAGAIN 10 IDYES 6 Description

The Abort button was selected.

The Cancel button was selected.

The Continue button was selected.

The Ignore button was selected.

The No button was selected.

The OK button was selected.

The Retry button was selected.

The Try Again button was selected.

The Yes button was selected.

Remarks
The following system icons can be used in a message box by setting the uType parameter to the corresponding flag value.
Icon Flag values MB_ICONHAND, MB_ICONSTOP, or MB_ICONERROR

MB_ICONQUESTION

MB_ICONEXCLAMATION or MB_ICONWARNING

MB_ICONASTERISK or MB_ICONINFORMATION

Adding two right-to-left marks (RLMs), represented by Unicode formatting character U+200F, in the beginning of a MessageBox display string is interpreted by the MessageBox rendering engine so as to cause the reading order of the MessageBox to be rendered as right-to-left (RTL). When you use a system-modal message box to indicate that the system is low on memory, the strings pointed to by the lpText and lpCaption parameters should not be taken from a resource file because an attempt to load the resource may fail. If you create a message box while a dialog box is present, use a handle to the dialog box as the hWnd parameter. The hWnd parameter should not identify a child window, such as a control in a dialog box.

Examples
In the following example, the application displays a message box that prompts the user for an action after an error condition has occurred. The message box displays the message that describes the error condition and how to resolve it. The MB_CANCELTRYCONTINUE style directs MessageBox to provide three buttons with which the user can choose how to proceed. The MB_DEFBUTTON2 style sets the default focus on the second button of the message box, in this case, the Try Again button.

Simple program to start


int DisplayResourceNAMessageBox() { int msgboxID = MessageBox( NULL, (LPCWSTR)L"Resource not available\nDo you want to try again?", (LPCWSTR)L"Account Details", MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2 ); switch (msgboxID) { case IDCANCEL: // TODO: add code break; case IDTRYAGAIN: // TODO: add code break; case IDCONTINUE: // TODO: add code break; } return msgboxID; }

The following image shows the output from the preceding code example:

Creating the Window


Once the class is registered, we can create a window with it. You should look up the paramters for CreateWindowEx() (as you should ALWAYS do when using a new API call), but I'll explain them briefly here.
HWND hwnd; hwnd = CreateWindowEx( WS_EX_CLIENTEDGE,

g_szClassName, "The title of my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL);

The first parameter (WS_EX_CLIENTEDGE) is the extended windows style, in this case I have set it to give it a sunken inner border around the window. Set it to 0 if you'd like to see the difference. Also play with other values to see what they do. Next we have the class name (g_szClassName), this tells the system what kind of window to create. Since we want to create a window from the class we just registered, we use the name of that class. After that we specify our window name or title which is the text that will be displayed in the Caption, or Title Bar on our window. The parameter we have as WS_OVERLAPPEDWINDOW is the Window Style parameter. There are quite a few of these and you should look them up and experiment to find out what they do. These will be covered more later. The next four parameters (CW_USEDEFAULT, CW_USEDEFAULT, 320, 240) are the X and Y co-ordinates for the top left corner of your window, and the width and height of the window. I've set the X and Y values to CW_USEDEFAULT to let windows choose where on the screen to put the window. Remeber that the left of the screen is an X value of zero and it increases to the right; The top of the screen is a Y value of zero which increases towards the bottom. The units are pixels, which is the smallest unit a screen can display at a given resolution. Next (NULL, NULL, g_hInst, NULL) we have the Parent Window handle, the menu handle, the application instance handle, and a pointer to window creation data. In windows, the windows on your screen are arranged in a heirarchy of parent and child windows. When you see a button on a window, the button is the Child and it is contained within the window that is it's Parent. In this example, the parent handle is NULL because we have no parent, this is our main or Top Level window. The menu is NULL for now since we don't have one yet. The instance handle is set to the value that is passed in as the first parameter to WinMain(). The creation data (which I almost never use) that can be used to send additional data to the window that is being created is also NULL. If you're wondering what this magic NULL is, it's simply defined as 0 (zero). Actually, in C it's defined as ((void*)0), since it's intended for use with pointers. Therefore you will possibly get warnings if you use NULL for integer

values, depending on your compiler and the warning level settings. You can choose to ignore the warnings, or just use 0 instead. Number one cause of people not knowing what the heck is wrong with their programs is probably that they didn't check the return values of their calls to see if they failed or not. CreateWindow() will fail at some point even if you're an experianced coder, simply because there are lots of mistakes that are easy to make. Untill you learn how to quickly identify those mistakes, at least give yourself the chance of figuring out where things go wrong, and Always check return values!
if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; }

After we've created the window and checked to make sure we have a valid handle we show the window, using the last parameter in WinMain() and then update it to ensure that it has properly redrawn itself on the screen.
ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd);

The nCmdShow parameter is optional, you could simply pass in SW_SHOWNORMAL all the time and be done with it. However using the parameter passed into WinMain() gives whoever is running your program to specify whether or not they want your window to start off visible, maximized, minimized, etc... You will find options for these in the properties of windows shortcuts, and this parameter is how the choice is carried out.

Practical Learning: Creating a Sample Application


1. Replace the file with the following (the file in Borland C++ Builder contains some lines with #pragma; you don't need to delete these files because their presence or absence will not have a negative impact on the compilation of the program): #include <windows.h> LPCTSTR ClsName = L"BasicApp"; LPCTSTR WndName = L"A Simple Window"; LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

MSG Msg; HWND hWnd; WNDCLASSEX WndClsEx; // Create the application window WndClsEx.cbSize = sizeof(WNDCLASSEX); WndClsEx.style = CS_HREDRAW | CS_VREDRAW; WndClsEx.lpfnWndProc = WndProcedure; WndClsEx.cbClsExtra = 0; WndClsEx.cbWndExtra = 0; WndClsEx.hIcon = LoadIcon(NULL, IDI_APPLICATION); WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW); WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); WndClsEx.lpszMenuName = NULL; WndClsEx.lpszClassName = ClsName; WndClsEx.hInstance = hInstance; WndClsEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // Register the application RegisterClassEx(&WndClsEx); // Create the window object hWnd = CreateWindow(ClsName, WndName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); // Find out if the window was created if( !hWnd ) // If the window was not created, return 0; // stop the application // Display the window to the user ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); // Decode and treat the messages // as long as the application is running while( GetMessage(&Msg, NULL, 0, 0) ) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {

switch(Msg) { // If the user wants to close the application case WM_DESTROY: // then close it PostQuitMessage(WM_QUIT); break; default: // Process the left-over messages return DefWindowProc(hWnd, Msg, wParam, lParam); } // If something was not done, let it go return 0; } 2. To execute the program, if you are using Borland C++ Builder, press F9 If you are using Microsoft Visual C++, press Ctrl + F5 and click Yes

3. To close the window, click its system Close button environment.

and return to your programming

http://comrade.ownz.com/docs/msvc6.html#f1help

You might also like