0% found this document useful (0 votes)
254 views

SDK Answers

The three most important members of the WNDCLASSEX structure are: 1. lpfnWndProc - A pointer to the window procedure for the class. 2. hInstance - A handle to the instance that contains the window procedure. 3. lpszClassName - A pointer to the window class name.

Uploaded by

Xitij Thool
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
254 views

SDK Answers

The three most important members of the WNDCLASSEX structure are: 1. lpfnWndProc - A pointer to the window procedure for the class. 2. hInstance - A handle to the instance that contains the window procedure. 3. lpszClassName - A pointer to the window class name.

Uploaded by

Xitij Thool
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 66

1. What is MSG structure?

2. MSG Structure
3. The MSG structure contains message information from a thread's message queue.
4. Syntax
5. Copy
6.
7. typedef struct {
8. HWND hwnd;
9. UINT message;
10. WPARAM wParam;
11. LPARAM lParam;
12. DWORD time;
13. POINT pt;
14. } MSG, *PMSG;
15.Members
16. hwnd
17. HWND
18. Handle to the window whose window procedure receives the message. hwnd is
NULL when the message is a thread message.
19. message
20. UINT
21. Specifies the message identifier. Applications can only use the low word; the high
word is reserved by the system.
22. wParam
23. WPARAM
24. Specifies additional information about the message. The exact meaning depends on
the value of the message member.
25. lParam
26. LPARAM
27. Specifies additional information about the message. The exact meaning depends on
the value of the message member.
28. time
29. DWORD
30. Specifies the time at which the message was posted.
31. pt
32. POINT
33. Specifies the cursor position, in screen coordinates, when the message was posted.
34.Requirements

Minimum supported client Windows XP


Minimum supported server Windows 2000 Server
Header Winuser.h (include Windows.h)

2. What function does the API DispatchMessage() perform ?

DispatchMessage Function
The DispatchMessage function dispatches a message to a window procedure. It is typically
used to dispatch a message retrieved by the GetMessage function.

Syntax

Copy
LRESULT DispatchMessage(
__in const MSG *lpmsg
);

Parameters

lpmsg [in]
MSG

Pointer to an MSG structure that contains the message.

Return Value

LRESULT

The return value specifies the value returned by the window procedure. Although its meaning
depends on the message being dispatched, the return value generally is ignored.

Remarks

The MSG structure must contain valid message values. If the lpmsg parameter points to a
WM_TIMER message and the lParam parameter of the WM_TIMER message is not
NULL, lParam points to a function that is called instead of the window procedure.

Note that the application is responsible for retrieving and dispatching input messages to the
dialog box. Most applications use the main message loop for this. However, to permit the
user to move to and to select controls by using the keyboard, the application must call
IsDialogMessage. For more information, see Dialog Box Keyboard Interface.

Examples

For an example, see Creating a Message Loop.

Requirements

Minimum supported client Windows XP


Minimum supported server Windows 2000 Server
Header Winuser.h (include Windows.h)
Library User32.lib
DLL User32.dll
DispatchMessageW (Unicode) and DispatchMessageA
Unicode and ANSI names
(ANSI)
3. Explain all four parameters to a WndProc() function.

WindowProc Function

The WindowProc function is an application-defined function that processes messages sent to


a window. The WNDPROC type defines a pointer to this callback function. WindowProc is
a placeholder for the application-defined function name.

Syntax

Copy
LRESULT CALLBACK WindowProc(
__in HWND hwnd,
__in UINT uMsg,
__in WPARAM wParam,
__in LPARAM lParam
);

Parameters

hwnd [in]
HWND

Handle to the window.

uMsg [in]
UINT

Specifies the message.

wParam [in]
WPARAM

Specifies additional message information. The contents of this parameter depend on


the value of the uMsg parameter.

lParam [in]
LPARAM

Specifies additional message information. The contents of this parameter depend on


the value of the uMsg parameter.

Return Value

LRESULT

The return value is the result of the message processing and depends on the message sent.
Remarks

To make your application more robust, you should use structured exception handling to trap
and handle any errors that might occur in the callback. The following code shows the guarded
body (various message handlers) in the __try, and exception filters and exception handler
block in the __except block.

Copy

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM


lParam)
{
__try
{
// guarded body
switch (message)
{
HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate);
HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand);
HANDLE_MSG(hwnd, WM_PAINT, Cls_OnPaint);
HANDLE_MSG(hwnd, WM_DESTROY, Cls_OnDestroy);
HANDLE_MSG(hwnd, WM_NOTIFY, Cls_OnNotify);
}
}
__except (filter-expression /* evaluate filter */)
{
// exception handler block
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

If your application runs on a 32-bit version of Windows operating system, uncaught


exceptions from the callback will be passed onto higher-level exception handlers of your
application when available.

However, if your application runs on a 64-bit version of Windows operating system or


WOW64, you should be aware that a 64-bit operating system handles uncaught exceptions
differently, based on its 64-bit processor and exception architecture, and calling convention.
The following table summarizes all possible ways of a 64-bit Windows operating system or
WOW64 handling uncaught exceptions.

Behavior
How the system handles uncaught exceptions
type
1 The system suppresses any uncaught exceptions.
The system first terminates the process, and then the Program Compatibility
Assistant (PCA) offers to fix it the next time you run the application. You can
2
disable the PCA mitigation by adding a Compatibility section to the application
manifest.
The system calls the exception filters but suppresses any uncaught exceptions
3
when it leaves the callback scope, without invoking the associated handlers.
 

The following table shows how a 64-bit version of Windows operating system or WOW64
handles uncaught exceptions. Notice that behavior type 2 only applies to the 64-bit version of
the Windows 7 operating system.

Operating System WOW64 64-bit Windows


Windows XP 3 1
Windows Server 2003 3 1
Windows Vista 3 1
Windows Vista SP1 1 1
Windows 7 1 2

Requirements

Minimum supported client Windows XP


Minimum supported server Windows 2000 Server
Header Winuser.h (include Windows.h)

4. Write the three most important members of the structure WNDCLASSEX.

WNDCLASSEX Structure

The WNDCLASSEX structure contains window class information. It is used with the
RegisterClassEx and GetClassInfoEx  functions.

The WNDCLASSEX structure is similar to the WNDCLASS structure. There are two
differences. WNDCLASSEX includes the cbSize member, which specifies the size of the
structure, and the hIconSm member, which contains a handle to a small icon associated with
the window class.

Syntax

Copy
typedef struct {
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;
Members

cbSize
UINT

Specifies the size, in bytes, of this structure. Set this member to


sizeof(WNDCLASSEX). Be sure to set this member before calling the
GetClassInfoEx function.

style
UINT

Specifies the class style(s). This member can be any combination of the Class Styles.

lpfnWndProc
WNDPROC

Pointer to the window procedure. You must use the CallWindowProc function to call
the window procedure. For more information, see WindowProc.

cbClsExtra
int

Specifies the number of extra bytes to allocate following the window-class structure.
The system initializes the bytes to zero.

cbWndExtra
int

Specifies the number of extra bytes to allocate following the window instance. The
system initializes the bytes to zero. If an application uses WNDCLASSEX to register
a dialog box created by using the CLASS directive in the resource file, it must set this
member to DLGWINDOWEXTRA.

hInstance
HINSTANCE

Handle to the instance that contains the window procedure for the class.

hIcon
HICON

Handle to the class icon. This member must be a handle to an icon resource. If this
member is NULL, the system provides a default icon.

hCursor
HCURSOR
Handle to the class cursor. This member must be a handle to a cursor resource. If this
member is NULL, an application must explicitly set the cursor shape whenever the
mouse moves into the application's window.

hbrBackground
HBRUSH

Handle to the class background brush. This member can be a handle to the physical
brush to be used for painting the background, or it can be a color value. A color value
must be one of the following standard system colors (the value 1 must be added to the
chosen color). If a color value is given, you must convert it to one of the following
HBRUSH types:

 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
 COLOR_WINDOWTEXT

The system automatically deletes class background brushes when the class is
unregistered by using UnregisterClass. An application should not delete these
brushes.

When this member is NULL, an application must paint its own background whenever
it is requested to paint in its client area. To determine whether the background must be
painted, an application can either process the WM_ERASEBKGND message or test
the fErase member of the PAINTSTRUCT structure filled by the BeginPaint
function.

lpszMenuName
LPCTSTR

Pointer to a null-terminated character string that specifies the resource name of the
class menu, as the name appears in the resource file. If you use an integer to identify
the menu, use the MAKEINTRESOURCE macro. If this member is NULL,
windows belonging to this class have no default menu.

lpszClassName
LPCTSTR

Pointer to a null-terminated string or is an atom. If this parameter is an atom, it must


be a class atom created by a previous call to the RegisterClass or RegisterClassEx
function. The atom must be in the low-order word of lpszClassName; the high-order
word must be zero.

If lpszClassName is a string, it specifies the window class name. The class name can
be any name registered with RegisterClass or RegisterClassEx, or any of the
predefined control-class names.

The maximum length for lpszClassName is 256. If lpszClassName is greater than


the maximum length, the RegisterClassEx function will fail.

hIconSm
HICON

Handle to a small icon that is associated with the window class. If this member is
NULL, the system searches the icon resource specified by the hIcon member for an
icon of the appropriate size to use as the small icon.

Requirements

Minimum supported client Windows XP


Minimum supported server Windows 2000 Server
Header Winuser.h (include Windows.h)
Unicode and ANSI names WNDCLASSEXW (Unicode) and WNDCLASSEXA (ANSI)

See Also

Reference
GetClassInfoEx
RegisterClassEx
UnregisterClass

5. How is ShowWindow()different from CreateWindow() ?

ShowWindow Function

The ShowWindow function sets the specified window's show state.

Syntax
Copy
BOOL ShowWindow(
__in HWND hWnd,
__in int nCmdShow
);

Parameters

hWnd [in]
HWND

Handle to the window.

nCmdShow [in]
int

Specifies how the window is to be shown. This parameter is ignored the first time an
application calls ShowWindow, if the program that launched the application provides
a STARTUPINFO structure. Otherwise, the first time ShowWindow is called, the
value should be the value obtained by the WinMain function in its nCmdShow
parameter. In subsequent calls, this parameter can be one of the following values.

SW_FORCEMINIMIZE

Minimizes a window, even if the thread that owns the window is not responding. This
flag should only be used when minimizing windows from a different thread.

SW_HIDE

Hides the window and activates another window.

SW_MAXIMIZE

Maximizes the specified window.

SW_MINIMIZE

Minimizes the specified window and activates the next top-level window in the Z
order.

SW_RESTORE

Activates and displays the window. If the window is minimized or maximized, the
system restores it to its original size and position. An application should specify this
flag when restoring a minimized window.

SW_SHOW

Activates the window and displays it in its current size and position.
SW_SHOWDEFAULT

Sets the show state based on the SW_ value specified in the STARTUPINFO
structure passed to the CreateProcess function by the program that started the
application.

SW_SHOWMAXIMIZED

Activates the window and displays it as a maximized window.

SW_SHOWMINIMIZED

Activates the window and displays it as a minimized window.

SW_SHOWMINNOACTIVE

Displays the window as a minimized window. This value is similar to


SW_SHOWMINIMIZED, except the window is not activated.

SW_SHOWNA

Displays the window in its current size and position. This value is similar to
SW_SHOW, except the window is not activated.

SW_SHOWNOACTIVATE

Displays a window in its most recent size and position. This value is similar to
SW_SHOWNORMAL, except the window is not actived.

SW_SHOWNORMAL

Activates and displays a window. If the window is minimized or maximized, the


system restores it to its original size and position. An application should specify this
flag when displaying the window for the first time.

Return Value

BOOL

If the window was previously visible, the return value is nonzero.

If the window was previously hidden, the return value is zero.

Remarks

To perform certain special effects when showing or hiding a window, use AnimateWindow.

The first time an application calls ShowWindow, it should use the WinMain function's
nCmdShow parameter as its nCmdShow parameter. Subsequent calls to ShowWindow must
use one of the values in the given list, instead of the one specified by the WinMain function's
nCmdShow parameter.

As noted in the discussion of the nCmdShow parameter, the nCmdShow value is ignored in
the first call to ShowWindow if the program that launched the application specifies startup
information in the structure. In this case, ShowWindow uses the information specified in the
STARTUPINFO structure to show the window. On subsequent calls, the application must
call ShowWindow with nCmdShow set to SW_SHOWDEFAULT to use the startup
information provided by the program that launched the application. This behavior is designed
for the following situations:

 Applications create their main window by calling CreateWindow with the


WS_VISIBLE flag set.
 Applications create their main window by calling CreateWindow with the
WS_VISIBLE flag cleared, and later call ShowWindow with the SW_SHOW flag set
to make it visible.

Examples

For an example, see Creating a Main Window.

Requirements

Minimum supported client Windows XP


Minimum supported server Windows 2000 Server
Header Winuser.h (include Windows.h)
Library User32.lib
DLL User32.dll
Unicode and ANSI names ShowWindowW (Unicode)

CreateWindow Function

The CreateWindow function creates an overlapped, pop-up, or child window. It specifies the
window class, window title, window style, and (optionally) the initial position and size of the
window. The function also specifies the window's parent or owner, if any, and the window's
menu.

To use extended window styles in addition to the styles supported by CreateWindow, use
the CreateWindowEx function.

Syntax

Copy
HWND CreateWindow(
__in LPCTSTR lpClassName,
__in LPCTSTR lpWindowName,
__in DWORD dwStyle,
__in int x,
__in int y,
__in int nWidth,
__in int nHeight,
__in HWND hWndParent,
__in HMENU hMenu,
__in HINSTANCE hInstance,
__in LPVOID lpParam
);

Parameters

lpClassName [in]
LPCTSTR

Pointer to a null-terminated string or a class atom created by a previous call to the


RegisterClass or RegisterClassEx function. The atom must be in the low-order word
of lpClassName; the high-order word must be zero. If lpClassName is a string, it
specifies the window class name. The class name can be any name registered with
RegisterClass or RegisterClassEx, provided that the module that registers the class
is also the module that creates the window. The class name can also be any of the
predefined system class names. For a list of system class names, see the Remarks
section.

lpWindowName [in]
LPCTSTR

Pointer to a null-terminated string that specifies the window name. If the window
style specifies a title bar, the window title pointed to by lpWindowName is displayed
in the title bar. When using CreateWindow to create controls, such as buttons, check
boxes, and static controls, use lpWindowName to specify the text of the control. When
creating a static control with the SS_ICON style, use lpWindowName to specify the
icon name or identifier. To specify an identifier, use the syntax "#num".

dwStyle [in]
DWORD

Specifies the style of the window being created. This parameter can be a combination
of

window styles
, plus the control styles indicated in the Remarks section.
x [in]
int

Specifies the initial horizontal position of the window. For an overlapped or pop-up
window, the x parameter is the initial x-coordinate of the window's upper-left corner,
in screen coordinates. For a child window, x is the x-coordinate of the upper-left
corner of the window relative to the upper-left corner of the parent window's client
area. If this parameter is set to CW_USEDEFAULT, the system selects the default
position for the window's upper-left corner and ignores the y parameter.
CW_USEDEFAULT is valid only for overlapped windows; if it is specified for a
pop-up or child window, the x and y parameters are set to zero.

y [in]
int

Specifies the initial vertical position of the window. For an overlapped or pop-up
window, the y parameter is the initial y-coordinate of the window's upper-left corner,
in screen coordinates. For a child window, y is the initial y-coordinate of the upper-
left corner of the child window relative to the upper-left corner of the parent window's
client area. For a list box, y is the initial y-coordinate of the upper-left corner of the
list box's client area relative to the upper-left corner of the parent window's client
area.

If an overlapped window is created with the WS_VISIBLE style bit set and the x
parameter is set to CW_USEDEFAULT, then the y parameter determines how the
window is shown. If the y parameter is CW_USEDEFAULT, then the window
manager calls ShowWindow with the SW_SHOW flag after the window has been
created. If the y parameter is some other value, then the window manager calls
ShowWindow with that value as the nCmdShow parameter.

nWidth [in]
int

Specifies the width, in device units, of the window. For overlapped windows, nWidth
is either the window's width, in screen coordinates, or CW_USEDEFAULT. If
nWidth is CW_USEDEFAULT, the system selects a default width and height for the
window; the default width extends from the initial x-coordinate to the right edge of
the screen, and the default height extends from the initial y-coordinate to the top of
the icon area. CW_USEDEFAULT is valid only for overlapped windows; if
CW_USEDEFAULT is specified for a pop-up or child window, nWidth and nHeight
are set to zero.

nHeight [in]
int

Specifies the height, in device units, of the window. For overlapped windows,
nHeight is the window's height, in screen coordinates. If nWidth is set to
CW_USEDEFAULT, the system ignores nHeight.

hWndParent [in]
HWND

Handle to the parent or owner window of the window being created. To create a child
window or an owned window, supply a valid window handle. This parameter is
optional for pop-up windows.

To create a message-only window, supply HWND_MESSAGE or a handle to an


existing message-only window.
hMenu [in]
HMENU

Handle to a menu, or specifies a child-window identifier depending on the window


style. For an overlapped or pop-up window, hMenu identifies the menu to be used
with the window; it can be NULL if the class menu is to be used. For a child window,
hMenu specifies the child-window identifier, an integer value used by a dialog box
control to notify its parent about events. The application determines the child-window
identifier; it must be unique for all child windows with the same parent window.

hInstance [in]
HINSTANCE

Handle to the instance of the module to be associated with the window.

lpParam [in]
LPVOID

Pointer to a value to be passed to the window through the CREATESTRUCT


structure (lpCreateParams member) pointed to by the lParam param of the
WM_CREATE message. This message is sent to the created window by this function
before it returns.

If an application calls CreateWindow to create a MDI client window, lpParam


should point to a CLIENTCREATESTRUCT structure. If an MDI client window
calls CreateWindow to create an MDI child window, lpParam should point to a
MDICREATESTRUCT structure. lpParam may be NULL if no additional data is
needed.

Return Value

HWND

If the function succeeds, the return value is a handle to the new window.

If the function fails, the return value is NULL. To get extended error information, call
GetLastError.

This function typically fails for one of the following reasons:

 an invalid parameter value


 the system class was registered by a different module
 The WH_CBT hook is installed and returns a failure code
 if one of the controls in the dialog template is not registered, or its window window
procedure fails WM_CREATE or WM_NCCREATE

Remarks
Before returning, CreateWindow sends a WM_CREATE message to the window
procedure. For overlapped, pop-up, and child windows, CreateWindow sends
WM_CREATE, WM_GETMINMAXINFO, and WM_NCCREATE messages to the
window. The lParam parameter of the WM_CREATE message contains a pointer to a
CREATESTRUCT structure. If the WS_VISIBLE style is specified, CreateWindow sends
the window all the messages required to activate and show the window.

If the created window is a child window, its default position is at the bottom of the Z-order. If
the created window is a top-level window, its default position is at the top of the Z-order (but
beneath all topmost windows unless the created window is itself topmost).

For information on controlling whether the Taskbar displays a button for the created window,
see Managing Taskbar Buttons.

For information on removing a window, see the DestroyWindow function.

The following predefined system classes can be specified in the lpClassName parameter.
Note the corresponding control styles you can use in the dwStyle parameter.

System class Meaning


Designates a small rectangular child window that represents a button the
user can click to turn it on or off. Button controls can be used alone or in
groups, and they can either be labeled or appear without text. Button
controls typically change appearance when the user clicks them. For
BUTTON
more information, see Buttons.

For a table of the button styles you can specify in the dwStyle parameter,
see Button Styles.
Designates a control consisting of a list box and a selection field similar
to an edit control. When using this style, an application should either
display the list box at all times or enable a drop-down list box. If the list
box is visible, typing characters into the selection field highlights the
first list box entry that matches the characters typed. Conversely,
COMBOBOX
selecting an item in the list box displays the selected text in the selection
field.

For more information, see Combo Boxes. For a table of the combo box
styles you can specify in the dwStyle parameter, see Combo Box Styles.
Designates a rectangular child window into which the user can type text
from the keyboard. The user selects the control and gives it the keyboard
focus by clicking it or moving to it by pressing the TAB key. The user
can type text when the edit control displays a flashing caret; use the
mouse to move the cursor, select characters to be replaced, or position
EDIT
the cursor for inserting characters; or use the BACKSPACE key to
delete characters. For more information, see Edit Controls.

For a table of the edit control styles you can specify in the dwStyle
parameter, see Edit Control Styles.
LISTBOX Designates a list of character strings. Specify this control whenever an
application must present a list of names, such as file names, from which
the user can choose. The user can select a string by clicking it. A
selected string is highlighted, and a notification message is passed to the
parent window. For more information, see List Boxes.

For a table of the list box styles you can specify in the dwStyle
parameter, see List Box Styles.
Designates an MDI client window. This window receives messages that
control the MDI application's child windows. The recommended style
bits are WS_CLIPCHILDREN and WS_CHILD. Specify the
MDICLIENT WS_HSCROLL and WS_VSCROLL styles to create an MDI client
window that allows the user to scroll MDI child windows into view.

For more information, see Multiple Document Interface.


Designates a Microsoft Rich Edit 1.0 control. This window lets the user
view and edit text with character and paragraph formatting, and can
include embedded Component Object Model (COM) objects. For more
RichEdit information, see Rich Edit Controls.

For a table of the rich edit control styles you can specify in the dwStyle
parameter, see Rich Edit Control Styles.
Designates a Microsoft Rich Edit 2.0 control. This controls let the user
view and edit text with character and paragraph formatting, and can
include embedded COM objects. For more information, see Rich Edit
RICHEDIT_CLASS Controls.

For a table of the rich edit control styles you can specify in the dwStyle
parameter, see Rich Edit Control Styles.
Designates a rectangle that contains a scroll box and has direction
arrows at both ends. The scroll bar sends a notification message to its
parent window whenever the user clicks the control. The parent window
is responsible for updating the position of the scroll box, if necessary.
SCROLLBAR
For more information, see Scroll Bars.

For a table of the scroll bar control styles you can specify in the dwStyle
parameter, see Scroll Bar Control Styles.
Designates a simple text field, box, or rectangle used to label, box, or
separate other controls. Static controls take no input and provide no
output. For more information, see Static Controls.
STATIC
For a table of the static control styles you can specify in the dwStyle
parameter, see Static Control Styles.

Examples

For an example, see Using Window Classes.


Requirements

Minimum supported client Windows XP


Minimum supported server Windows 2000 Server
Header Winuser.h (include Windows.h)
Library User32.lib
DLL User32.dll
Unicode and ANSI names CreateWindowW (Unicode) and CreateWindowA (ANSI)

--------------------------------------------------------------------------------------------------------------------------------
-

6. What is a CALLBACK function? Give an example.


Creating a Callback Function

You can determine whether a DLL function requires a callback function by looking at its
arguments and reading the documentation for the function. An argument that takes a pointer
to a callback function is a long pointer, usually prefaced with the prefix "lp". Also, the name
of the argument usually ends in "Func", indicating that it takes a pointer to a function. For
example, take a look at the Declare statement for the EnumWindows function. The
lpEnumFunc argument indicates that the function requires a callback function.

Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, _


              ByVal lngParam As Long) As Long

So how do you know what the callback function should look like? The answer is in the
documentation for the function. Each callback function has different arguments.
Unfortunately, although information about DLL functions requiring callbacks is available in
Win32API.txt, information about creating the callback functions themselves is not.

The Microsoft Platform SDK, available on the Microsoft Developer Network site at
http://msdn.microsoft.com, contains information about all DLL functions that require
callbacks and their corresponding callback functions, and is probably the best source for this
information. However, in order to use it, you need to be able to interpret C/C++
documentation and translate it to VBA.

You can name the callback function whatever you want to; the suggested name is usually the
name of the DLL function, followed by "Proc". For example, the suggested name for the
callback function of the EnumWindows function is EnumWindowsProc. Note that you can
have more than one callback function for the same DLL function.

Here's the C/C++ definition for the EnumWindowsProc function, as described in the Platform
SDK:

BOOL CALLBACK EnumWindowsProc(


   HWND hwnd, // handle to parent window
   LPARAM lParam // application-defined value
);

Translated to VBA, this function becomes:


Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
End Function

The hwnd argument is a handle to a window. The lParam argument is an application-defined


argument that can be any data type. The value that you pass to the lParam argument for the
EnumWindows function is also the value passed to the lParam argument of the
EnumWindowsProc function. You don't have to define lParam as a Long; you can define it
as another type if you know that you will be passing in, say, a ListBox control, or an array.
Also, you don't have to pass any value to lParam at all.

Callback functions usually return a Long value - nonzero for success, zero for failure. To
continue enumerating, a callback function must return True, so you must explicitly set the
return value to True within the function. Setting it to False halts the enumeration. The
function will run until it either finishes enumerating or returns False.

Important   Be careful when defining the callback function. You must include the ByVal
keyword where necessary, and you must include the return value for the function. Also, the
function must be declared exactly according to the documentation. If you don't define the
function correctly, your solution will most likely cause an application error when you try to
run it.

When you call the EnumWindows function, this function calls the EnumWindowsProc
function in your VBA project for each existing window, passing in the window's handle and
whatever value is contained in the lParam argument. You can add whatever code you want
within the callback function.

The following example shows a callback function for the EnumWindows function. This
callback function, EnumWindowsProc, adds each visible parent window to the
ParentWindows collection, a custom collection of ParentWindow objects. In order to add
windows to the collection, the collection object is passed into the callback function in the
lParam argument. The procedure calls two other functions: the IsWindowVisible API
function, which determines whether a given window is visible, and the GetWindowCaption
procedure, which in turn calls the GetWindowText API function to return the window's
caption.

Note   Parent windows are primary application windows; child windows are windows that
exist within parent windows. A separate DLL function, EnumChildWindows, exists for
enumerating child windows within parent windows. The EnumWindows.xls sample file
demonstrates both functions.

Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Object) As


Long
   ' Add all visible windows to ParentWindows collection.
   ' This is the callback function called by EnumWindows.
   '
   ' The hWnd argument provides a handle to a specific window each time
   ' the callback function runs.
   ' The lParam argument can take any data that the user wants to pass to
   ' the function. In this case, it is defined as type Object, so that
   ' the EnumWindows function can pass in a reference to the ParentWindows
   ' collection.
   '
   ' You could use this function to return both visible and non-visible
   ' windows by removing the code that calls the IsWindowVisible function.
   
   Dim strCaption As String
   Dim pwnNew As ParentWindow
   
   ' Check whether this window is visible.
   If IsWindowVisible(hWnd) Then
      ' Add new ParentWindow object to ParentWindows collection.
      Set pwnNew = lParam.Add(hWnd)
      ' Call function to enumerate child windows.
      EnumChildWindows hWnd, AddressOf EnumChildWindowsProc, _
         pwnNew.ChildWindows
   End If

   ' Return True to continue enumerating windows.


   ' Function will stop running when all windows have been
   ' enumerated.
   EnumWindowsProc = True
End Function

The EnumWindowsProc callback function is available in the modEnumWindows module in


EnumWindows.xls in the ODETools\V9\Samples\OPG\Samples\CH10 subfolder on the
Office 2000 Developer CD-ROM. This procedure is used to create objects in a small custom
object model. The ParentWindows collection contains ParentWindow objects, which refer to
individual visible windows. The address of the EnumWindowsProc function is passed to the
EnumWindows function, which is called from the Class_Initialize event procedure for the
ParentWindows collection, so that the existing windows are immediately added to the
collection.

Once the ParentWindows collection has been initialized, you can refer to a ParentWindow
object within the collection by its index or by its key, which is the window's handle. Use the
Item property of the ParentWindows collection to refer to a member of the collection. For
example, the following code fragment prints the caption of the third ParentWindow object in
the ParentWindows collection:

Debug.Print ParentWindows.Item(3).Caption

7. How do you establish a message loop in a Windows program?

GetMessage Function

The GetMessage function retrieves a message from the calling thread's message queue. The
function dispatches incoming sent messages until a posted message is available for retrieval.

Unlike GetMessage, the PeekMessage function does not wait for a message to be posted
before returning.

Syntax

Copy
BOOL GetMessage(
__out LPMSG lpMsg,
__in HWND hWnd,
__in UINT wMsgFilterMin,
__in UINT wMsgFilterMax
);

Parameters

lpMsg [out]
LPMSG

Pointer to an MSG structure that receives message information from the thread's
message queue.

hWnd [in]
HWND

Handle to the window whose messages are to be retrieved. The window must belong
to the current thread.

If hWnd is NULL, GetMessage retrieves messages for any window that belongs to
the current thread, and any messages on the current thread's message queue whose
hwnd value is NULL (see the MSG structure). Therefore if hWnd is NULL, both
window messages and thread messages are processed.

If hWnd is -1, GetMessage retrieves only messages on the current thread's message
queue whose hwnd value is NULL, that is, thread messages as posted by
PostMessage (when the hWnd parameter is NULL) or PostThreadMessage.

wMsgFilterMin [in]
UINT

Specifies the integer value of the lowest message value to be retrieved. Use
WM_KEYFIRST to specify the first keyboard message or WM_MOUSEFIRST to
specify the first mouse message.

Windows XP: Use WM_INPUT here and in wMsgFilterMax to specify only the
WM_INPUT messages.

If wMsgFilterMin and wMsgFilterMax are both zero, GetMessage returns all


available messages (that is, no range filtering is performed).

wMsgFilterMax [in]
UINT

Specifies the integer value of the highest message value to be retrieved. Use
WM_KEYLAST to specify the last keyboard message or WM_MOUSELAST to
specify the last mouse message.

Windows XP: Use WM_INPUT here and in wMsgFilterMin to specify only the
WM_INPUT messages.
If wMsgFilterMin and wMsgFilterMax are both zero, GetMessage returns all
available messages (that is, no range filtering is performed).

Return Value

BOOL

If the function retrieves a message other than WM_QUIT, the return value is nonzero.

If the function retrieves the WM_QUIT message, the return value is zero.

If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid
window handle or lpMsg is an invalid pointer. To get extended error information, call
GetLastError.

Warning  

Because the return value can be nonzero, zero, or -1, avoid code like this:

Copy
while (GetMessage( lpMsg, hWnd, 0, 0)) ...

The possibility of a -1 return value means that such code can lead to fatal application errors.
Instead, use code like this:

Copy
BOOL bRet;

while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)


{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

Remarks

An application typically uses the return value to determine whether to end the main message
loop and exit the program.

The GetMessage function retrieves messages associated with the window identified by the
hWnd parameter or any of its children, as specified by the IsChild function, and within the
range of message values given by the wMsgFilterMin and wMsgFilterMax parameters. Note
that an application can only use the low word in the wMsgFilterMin and wMsgFilterMax
parameters; the high word is reserved for the system.
Note that GetMessage always retrieves WM_QUIT messages, no matter which values you
specify for wMsgFilterMin and wMsgFilterMax.

During this call, the system delivers pending, nonqueued messages, that is, messages sent to
windows owned by the calling thread using the SendMessage, SendMessageCallback,
SendMessageTimeout, or SendNotifyMessage function. Then the first queued message that
matches the specified filter is retrieved. The system may also process internal events. If no
filter is specified, messages are processed in the following order:

 Sent messages
 Posted messages
 Input (hardware) messages and system internal events
 Sent messages (again)
 WM_PAINT messages
 WM_TIMER messages

To retrieve input messages before posted messages, use the wMsgFilterMin and
wMsgFilterMax parameters.

GetMessage does not remove WM_PAINT messages from the queue. The messages remain
in the queue until processed.

Windows XP: If a top-level window stops responding to messages for more than several
seconds, the system considers the window to be not responding and replaces it with a ghost
window that has the same z-order, location, size, and visual attributes. This allows the user to
move it, resize it, or even close the application. However, these are the only actions available
because the application is actually not responding. When in the debugger mode, the system
does not generate a ghost window.

Examples

For an example, see Creating a Message Loop.

Requirements

Minimum supported client Windows XP


Minimum supported server Windows 2000 Server
Header Winuser.h (include Windows.h)
Library User32.lib
DLL User32.dll
Unicode and ANSI names GetMessageW (Unicode) and GetMessageA (ANSI)

8. Name any 5 mouse messages.


Low-Level Mouse Hook in C#

After my last post on implementing low-level keyboard hooks in C#, Soumitra asked if it was
possible to implement a low-level mouse hook in C#, too.  Sure.  Here is an example that will
print out the location of the mouse every time you press the left mouse button down:

class InterceptMouse
{
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;

public static void Main()


{
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
}

private static IntPtr SetHook(LowLevelMouseProc proc)


{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}

private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam,


IntPtr lParam);

private static IntPtr HookCallback(


int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 &&
MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct =
(MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

private const int WH_MOUSE_LL = 14;

private enum MouseMessages


{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}

[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}

[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]


private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]


[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]


private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError =


true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}

9. Name any 5 keyboard messages.

10. What are virtual key codes? How they are different from Scan codes? How they are different
from ASCII
codes?

11. What arrangements have to be made with the WNDCLASSEX structure of a Window class to
start getting
WM_DBLCLKS messages for double clicks of mouse?
12. What are the contents of wParam and lParam for a mouse message?
13. Which APIs are used to set and destroy Timers?
14. What are the contents of wParam and lParam for the WM_COMMAND message related with
a menu?
15. Write the steps involved in creating a menu through a resource editor.
16. What are the contents of LOWORD(wParam), HIWORD(wParam) and lParam for messages
related with
child window control?
17. A check box is created from a CheckBox class. (T/F)
18. Explain the purpose of the API GetDlgItem()
19. Write a code snippet to demonstrate the use of SendMessage() in context of child window
controls.
20. Name any four system control classes.
21. What are common dialogs? Name three common dialogs.
22. What are windows resources?
23. Name any 5 resources.
24. What is the difference between a modal and a modeless dialog box?
25. Name any 5 GDI objects.
26. What are stock GDI objects?
27. What is a clipboard? What are different clipboard formats?
28. How many bytes are there in a UNICODE character?
29. A dynamic link library gives us better speed performance than a static link library. (T/F)
30. What is a Resource Only Library?
31. Show the hierarchical relationship among a Frame window, Client window and Child window
in a MDI
application.
32. “While programming for Windows in C using SDK, we simulate Object Oriented
Programming”. Justify
this statement
33. In a typical Windows program we have one WinMain() function and one WndProc() function.
34. How is
WndProc() called automatically when there is no explicit call to it in the WinMain() ?
35. When do you get the message WM_PAINT? Why do you trap the WM_PAINT message and
not the
WM_CREATE message to write TextOut() in a typical “HelloWorld” program?
36. What is GDI? Why it is advised to use BeginPaint() and EndPaint() in pairs?
37. What happens when you register a window? How is RegisterClassEx()different from
CreateWindow()?
38. Is it always necessary to call DefWindowProc() at the end of your WndProc()? If not what
extra piece of
code will have to be written by the programmer?
39. What is the difference between the members hIcon and hIconSm of the WNDCLASSEX
structure ?
40. How does Windows achieve device independence by the use of GDI?
41. What type of translation is carried out in the API TranslateMessage() ?
ACTS National Resource Center, Pune
Question Bank –Win32 SDK (Solved)
Page 13 of 13
42. Is it possible to have more WM_KEYDOWN messages than WM_KEYUP messages? When
does such
situation occur?
43. Write an appropriate code snippet to demonstrate the use of InvalidateRect() in response to a
WM_CHAR message?
44. How do you get the status of SHIFT keys while processing a mouse message?
45. Name any 5 menu related messages.
46. What is subclassing? Write the steps and necessary APIs to subclass an edit class.
47. Write a code snippet that is required to bring a Color Dialog Box on screen.
48. In a small piece of code show the use of the API SetCursor().
49. Write the message loop for a program which uses a modeless dialog box.
50. Explain the use of the following APIs:
GetDlgItemText() GetDlgItemInt()
51. Explain the meaning of the following style flags related with a Window Class. CS_CLASSDC,
CS_PARENTDC, CS_OWNDC.
52. Explain with example the use of BitBlit() API.
53. How a logical font is created? Explain with appropriate APIs and Structures.
54. What are Meta files ?
55. Write a small piece of code to demonstrate the creation of a meta file.
56. Explain the following APIs.:
OpenClipboard() IsClipboardFormatAvailable()
57. Explain the following APIs.:
EmptyClipboard(), SetClipboardData(), SetClipboardViewer()
58. How these messages are used.
WM_COPY WM_PASTE
WM_PAINTCLIPBOARD WM_CHANGECBCHAIN
59. How UNICODE can be useful in bringing all the languages on computers?
60. A dynamic link library gives us better speed performance than a static link library. (T/F)Justify
your
answer.
Answer the following in details:
1. Write the steps involved in creating a DLL and then using it in a program. Put two functions
AddTwoNums() and MultiplyTwoNums() inside the DLL. Write the code snippets to create the
DLL.
2. What do you understand by Entry/Exit function in a DLL? How they are used?
3. Explain with example code snippets, the use of following structures.
MDICREATESTRUCT CLIENTCREATESTRUCT
4. Write the messages generated in proper order when a key is pressed which indicates:
System keystroke message
Non-system keystroke message
5. What is meant by a CALLBACK function. Which functions should be declared as CALLBACK?
6. What is window subclassing ? Write the skeleton of the steps required in subclassing a
window.
7. What is the significance of the value returned by the Window Procedure while handling
WM_CREATE
message?
8. What are the values send in WPARAM and LPARAM with the following messages?
WM_PAINT
WM_CREATE
WM_COMMAND
WM_MOUSEMOVE
ACTS National Resource Center, Pune
Question Bank –Win32 SDK (Solved)
Page 14 of 14
9. Write Win32 statements for the following
a. Copy the selected text in a text box to clipboard.
b. Change the state of a radio button.
10. Write Win32 statements for the following
a) Count the number of items in a list box.
b) Change the title of any window.

11. Describe the use of the following APIs/C Library Functions by writing your own sample code:
a) _beginthread()
_beginthread, _beginthreadex 

Creates a thread.

Copy

uintptr_t _beginthread(
void( *start_address )( void * ),
unsigned stack_size,
void *arglist
);
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
Parameters
start_address

Start address of a routine that begins execution of a new thread. For _beginthread,
the calling convention is either __cdecl or __clrcall; for _beginthreadex, it is either
__stdcall or __clrcall.

stack_size

Stack size for a new thread or 0.

arglist

Argument list to be passed to a new thread or NULL.

security

Pointer to a SECURITY_ATTRIBUTES structure that determines whether the


returned handle can be inherited by child processes. If NULL, the handle cannot be
inherited. Must be NULL for Windows 95 applications.

initflag

Initial state of a new thread (0 for running or CREATE_SUSPENDED for


suspended); use ResumeThread to execute the thread.

thrdaddr

Points to a 32-bit variable that receives the thread identifier. Might be NULL, in
which case it is not used.

Return Value

If successful, each of these functions returns a handle to the newly created thread; however, if
the newly created thread exits too quickly, _beginthread might not return a valid handle (see
the discussion in the Remarks section). _beginthread returns -1L on an error, in which case
errno is set to EAGAIN if there are too many threads, to EINVAL if the argument is invalid
or the stack size is incorrect, or to EACCES in the case of insufficient resources (such as
memory). _beginthreadex returns 0 on an error, in which case errno and _doserrno are set.

If startaddress is NULL, the invalid parameter handler is invoked, as described in Parameter


Validation. If execution is allowed to continue, these functions set errno to EINVAL and
return -1.

For more information about these and other return codes, see _doserrno, errno, _sys_errlist,
and _sys_nerr.
For more information about uintptr_t, see Standard Types.

Remarks

The _beginthread function creates a thread that begins execution of a routine at


start_address. The routine at start_address must use the __cdecl calling convention and
should have no return value. When the thread returns from that routine, it is terminated
automatically. For more information about threads, see Multithreading.

_beginthreadex resembles the Win32 CreateThread API more closely than _beginthread
does. _beginthreadex differs from _beginthread in the following ways:

 _beginthreadex has three additional parameters: initflag, security, and threadaddr.


The new thread can be created in a suspended state, with a specified security
(Windows NT only), and can be accessed using thrdaddr, which is the thread
identifier.

 The routine at start_address passed to _beginthreadex must use the __stdcall calling
convention and must return a thread exit code.

 _beginthreadex returns 0 on failure, rather than -1L.

 A thread created with _beginthreadex is terminated by a call to _endthreadex.

The _beginthreadex function gives you more control over how the thread is created than
_beginthread does. The _endthreadex function is also more flexible. For example, with
_beginthreadex, you can use security information, set the initial state of the thread (running
or suspended), and get the thread identifier of the newly created thread. You are also able to
use the thread handle returned by _beginthreadex with the synchronization APIs, which you
cannot do with _beginthread.

It is safer to use _beginthreadex than _beginthread. If the thread generated by


_beginthread exits quickly, the handle returned to the caller of _beginthread might be
invalid or, worse, point to another thread. However, the handle returned by _beginthreadex
has to be closed by the caller of _beginthreadex, so it is guaranteed to be a valid handle if
_beginthreadex did not return an error.

You can call _endthread or _endthreadex explicitly to terminate a thread; however,


_endthread or _endthreadex is called automatically when the thread returns from the
routine passed as a parameter. Terminating a thread with a call to endthread or
_endthreadex helps to ensure proper recovery of resources allocated for the thread.

_endthread automatically closes the thread handle (whereas _endthreadex does not).
Therefore, when using _beginthread and _endthread, do not explicitly close the thread
handle by calling the Win32 CloseHandle API. This behavior differs from the Win32
ExitThread API.

Note
For an executable file linked with Libcmt.lib, do not call the Win32 ExitThread API; this
prevents the run-time system from reclaiming allocated resources. _endthread and
_endthreadex reclaim allocated thread resources and then call ExitThread.

The operating system handles the allocation of the stack when either _beginthread or
_beginthreadex is called; you do not need to pass the address of the thread stack to either of
these functions. In addition, the stack_size argument can be 0, in which case the operating
system uses the same value as the stack specified for the main thread.

arglist is a parameter to be passed to the newly created thread. Typically it is the address of a
data item, such as a character string. arglist can be NULL if it is not needed, but
_beginthread and _beginthreadex must be provided with some value to pass to the new
thread. All threads are terminated if any thread calls abort, exit, _exit, or ExitProcess.

The locale of the new thread is inherited from its parent thread. If per thread locale is enabled
by a call to _configthreadlocale (either globally or for new threads only), the thread can
change its locale independently from its parent by calling setlocale or _wsetlocale. For more
information, see Locale.

For mixed and pure code, _beginthread and _beginthreadex both have two overloads, one
taking a native calling-convention function pointer, the other taking a __clrcall function
pointer. The first overload is not application domain-safe and never will be. If you are writing
mixed or pure code you must ensure that the new thread enters the correct application domain
before it accesses managed resources. You can do this, for example, by using
call_in_appdomain Function. The second overload is application domain-safe; the newly
created thread will always end up in the application domain of the caller of _beginthread or
_beginthreadex.

Requirements

Required
Routine Compatibility
header

Windows 95, Windows 98, Windows 98 Second Edition,


Windows Millennium Edition, Windows Millennium Edition,
_beginthread <process.h>
Windows NT 4.0, Windows 2000, Windows XP Home
Edition, Windows XP Professional, Windows Server 2003
Windows 95, Windows 98, Windows 98 Second Edition,
Windows Millennium Edition, Windows Millennium Edition,
_beginthreadex <process.h>
Windows NT 4.0, Windows 2000, Windows XP Home
Edition, Windows XP Professional, Windows Server 2003

For more compatibility information, see Compatibility in the Introduction.

Libraries
Multithreaded versions of the C run-time libraries only.

To use _beginthread or _beginthreadex, the application must link with one of the
multithreaded C run-time libraries.

Example

The following example uses _beginthread and _endthread.

Copy

// crt_BEGTHRD.C
// compile with: /MT /D "_X86_" /c
// processor: x86
#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <stddef.h>
#include <stdlib.h>
#include <conio.h>

void Bounce( void *ch );


void CheckKey( void *dummy );

/* GetRandom returns a random integer between min and max. */


#define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) +
(min))

BOOL repeat = TRUE; /* Global repeat flag and video variable */


HANDLE hStdOut; /* Handle for console window */
CONSOLE_SCREEN_BUFFER_INFO csbi; /* Console information structure */

int main()
{
CHAR ch = 'A';

hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

/* Get display screen's text row and column information. */


GetConsoleScreenBufferInfo( hStdOut, &csbi );

/* Launch CheckKey thread to check for terminating keystroke. */


_beginthread( CheckKey, 0, NULL );

/* Loop until CheckKey terminates program. */


while( repeat )
{
/* On first loops, launch character threads. */
_beginthread( Bounce, 0, (void *) (ch++) );

/* Wait one second between loops. */


Sleep( 1000L );
}
}
/* CheckKey - Thread to wait for a keystroke, then clear repeat flag. */
void CheckKey( void *dummy )
{
_getch();
repeat = 0; /* _endthread implied */

/* Bounce - Thread to create and and control a colored letter that moves
* around on the screen.
*
* Params: ch - the letter to be moved
*/
void Bounce( void *ch )
{
/* Generate letter and color attribute from thread argument. */
char blankcell = 0x20;
char blockcell = (char) ch;
BOOL first = TRUE;
COORD oldcoord, newcoord;
DWORD result;

/* Seed random number generator and get initial location. */


srand( _threadid );
newcoord.X = GetRandom( 0, csbi.dwSize.X - 1 );
newcoord.Y = GetRandom( 0, csbi.dwSize.Y - 1 );
while( repeat )
{
/* Pause between loops. */
Sleep( 100L );

/* Blank out our old position on the screen, and draw new letter.
*/
if( first )
first = FALSE;
else
WriteConsoleOutputCharacter( hStdOut, &blankcell, 1, oldcoord,
&result );
WriteConsoleOutputCharacter( hStdOut, &blockcell, 1, newcoord,
&result );

/* Increment the coordinate for next placement of the block. */


oldcoord.X = newcoord.X;
oldcoord.Y = newcoord.Y;
newcoord.X += GetRandom( -1, 1 );
newcoord.Y += GetRandom( -1, 1 );

/* Correct placement (and beep) if about to go off the screen. */


if( newcoord.X < 0 )
newcoord.X = 1;
else if( newcoord.X == csbi.dwSize.X )
newcoord.X = csbi.dwSize.X - 2;
else if( newcoord.Y < 0 )
newcoord.Y = 1;
else if( newcoord.Y == csbi.dwSize.Y )
newcoord.Y = csbi.dwSize.Y - 2;

/* If not at a screen border, continue, otherwise beep. */


else
continue;
Beep( ((char) ch - 'A') * 100, 175 );
}
/* _endthread given to terminate */
_endthread();
}

Input
press any key to end

The following sample code demonstrates how you can use the thread handle returned by
_beginthreadex with the synchronization API WaitForSingleObject. The main thread waits
for the second thread to terminate before it continues. When the second thread calls
_endthreadex, it causes its thread object to go to the signaled state. This allows the primary
thread to continue running. This cannot be done with _beginthread and _endthread, because
_endthread calls CloseHandle, destroying the thread object before it can be set to the
signaled state.

Copy

// crt_begthrdex.cpp
// compile with: /MT
#include <windows.h>
#include <stdio.h>
#include <process.h>

unsigned Counter;
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
printf( "In second thread...\n" );

while ( Counter < 1000000 )


Counter++;

_endthreadex( 0 );
return 0;
}

int main()
{
HANDLE hThread;
unsigned threadID;

printf( "Creating second thread...\n" );

// Create the second thread.


hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0,
&threadID );

// Wait until second thread terminates. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 1000000 yet.
WaitForSingleObject( hThread, INFINITE );
printf( "Counter should be 1000000; it is-> %d\n", Counter );
// Destroy the thread object.
CloseHandle( hThread );
}
Output
Creating second thread...
In second thread...
Counter should be 1000000; it is-> 1000000

b) StretchBlt()

StretchBlt Function

The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle,
stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if
necessary. The system stretches or compresses the bitmap according to the stretching mode
currently set in the destination device context.

Syntax

Copy
BOOL StretchBlt(
__in HDC hdcDest,
__in int nXOriginDest,
__in int nYOriginDest,
__in int nWidthDest,
__in int nHeightDest,
__in HDC hdcSrc,
__in int nXOriginSrc,
__in int nYOriginSrc,
__in int nWidthSrc,
__in int nHeightSrc,
__in DWORD dwRop
);

Parameters

hdcDest [in]

A handle to the destination device context.

nXOriginDest [in]

The x-coordinate, in logical units, of the upper-left corner of the destination rectangle.

nYOriginDest [in]

The y-coordinate, in logical units, of the upper-left corner of the destination rectangle.

nWidthDest [in]
The width, in logical units, of the destination rectangle.

nHeightDest [in]

The height, in logical units, of the destination rectangle.

hdcSrc [in]

A handle to the source device context.

nXOriginSrc [in]

The x-coordinate, in logical units, of the upper-left corner of the source rectangle.

nYOriginSrc [in]

The y-coordinate, in logical units, of the upper-left corner of the source rectangle.

nWidthSrc [in]

The width, in logical units, of the source rectangle.

nHeightSrc [in]

The height, in logical units, of the source rectangle.

dwRop [in]

The raster operation to be performed. Raster operation codes define how the system
combines colors in output operations that involve a brush, a source bitmap, and a
destination bitmap.

See BitBlt for a list of common raster operation codes (ROPs). Note that the
CAPTUREBLT ROP generally cannot be used for printing device contexts.

Return Value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero.

Remarks

StretchBlt stretches or compresses the source bitmap in memory and then copies the result to
the destination rectangle. This bitmap can be either a compatible bitmap (DDB) or the output
from CreateDIBSection. The color data for pattern or destination pixels is merged after the
stretching or compression occurs.

When an enhanced metafile is being recorded, an error occurs (and the function returns
FALSE) if the source device context identifies an enhanced-metafile device context.
If the specified raster operation requires a brush, the system uses the brush currently selected
into the destination device context.

The destination coordinates are transformed by using the transformation currently specified
for the destination device context; the source coordinates are transformed by using the
transformation currently specified for the source device context.

If the source transformation has a rotation or shear, an error occurs.

If destination, source, and pattern bitmaps do not have the same color format, StretchBlt
converts the source and pattern bitmaps to match the destination bitmap.

If StretchBlt must convert a monochrome bitmap to a color bitmap, it sets white bits (1) to
the background color and black bits (0) to the foreground color. To convert a color bitmap to
a monochrome bitmap, it sets pixels that match the background color to white (1) and sets all
other pixels to black (0). The foreground and background colors of the device context with
color are used.

StretchBlt creates a mirror image of a bitmap if the signs of the nWidthSrc and nWidthDest
parameters or if the nHeightSrc and nHeightDest parameters differ. If nWidthSrc and
nWidthDest have different signs, the function creates a mirror image of the bitmap along the
x-axis. If nHeightSrc and nHeightDest have different signs, the function creates a mirror
image of the bitmap along the y-axis.

Not all devices support the StretchBlt function. For more information, see the
GetDeviceCaps.

ICM: No color management is performed when a blit operation occurs.

When used in a multiple monitor system, both hdcSrc and hdcDest must refer to the same
device or the function will fail. To transfer data between DCs for different devices, convert
the memory bitmap to a DIB by calling GetDIBits. To display the DIB to the second device,
call SetDIBits or StretchDIBits.

Examples

For an example, see Scaling an Image.

Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Wingdi.h (include Windows.h)
Library Gdi32.lib
DLL Gdi32.dll
c) StretchDIBits()

StretchDIBits Function

The StretchDIBits function copies the color data for a rectangle of pixels in a DIB, JPEG, or
PNG image to the specified destination rectangle. If the destination rectangle is larger than
the source rectangle, this function stretches the rows and columns of color data to fit the
destination rectangle. If the destination rectangle is smaller than the source rectangle, this
function compresses the rows and columns by using the specified raster operation.

Syntax

Copy
int StretchDIBits(
__in HDC hdc,
__in int XDest,
__in int YDest,
__in int nDestWidth,
__in int nDestHeight,
__in int XSrc,
__in int YSrc,
__in int nSrcWidth,
__in int nSrcHeight,
__in const VOID *lpBits,
__in const BITMAPINFO *lpBitsInfo,
__in UINT iUsage,
__in DWORD dwRop
);

Parameters

hdc [in]

A handle to the destination device context.

XDest [in]

The x-coordinate, in logical units, of the upper-left corner of the destination rectangle.

YDest [in]

The y-coordinate, in logical units, of the upper-left corner of the destination rectangle.

nDestWidth [in]

The width, in logical units, of the destination rectangle.

nDestHeight [in]

The height, in logical units, of the destination rectangle.


XSrc [in]

The x-coordinate, in pixels, of the source rectangle in the image.

YSrc [in]

The y-coordinate, in pixels, of the source rectangle in the image.

nSrcWidth [in]

The width, in pixels, of the source rectangle in the image.

nSrcHeight [in]

The height, in pixels, of the source rectangle in the image.

lpBits [in]

A pointer to the image bits, which are stored as an array of bytes. For more
information, see the Remarks section.

lpBitsInfo [in]

A pointer to a BITMAPINFO structure that contains information about the DIB.

iUsage [in]

Specifies whether the bmiColors member of the BITMAPINFO structure was


provided and, if so, whether bmiColors contains explicit red, green, blue (RGB)
values or indexes. The iUsage parameter must be one of the following values.

Value Meaning
The array contains 16-bit indexes into the logical palette of the
DIB_PAL_COLORS
source device context.
DIB_RGB_COLORS The color table contains literal RGB values.

For more information, see the Remarks section.

dwRop [in]

Specifies how the source pixels, the destination device context's current brush, and the
destination pixels are to be combined to form the new image. For more information,
see the following Remarks section.

Return Value
If the function succeeds, the return value is the number of scan lines copied. Note that this
value can be negative for mirrored content.

If the function fails, or no scan lines are copied, the return value is 0.

If the driver cannot support the JPEG or PNG file image passed to StretchDIBits, the
function will fail and return GDI_ERROR. If failure does occur, the application must fall
back on its own JPEG or PNG support to decompress the image into a bitmap, and then pass
the bitmap to StretchDIBits.

Remarks

The origin of a bottom-up DIB is the bottom-left corner; the origin of a top-down DIB is the
upper-left corner.

StretchDIBits creates a mirror image of a bitmap if the signs of the nSrcWidth and
nDestWidth parameters, or if the nSrcHeight and nDestHeight parameters differ. If
nSrcWidth and nDestWidth have different signs, the function creates a mirror image of the
bitmap along the x-axis. If nSrcHeight and nDestHeight have different signs, the function
creates a mirror image of the bitmap along the y-axis.

This function allows a JPEG or PNG image to be passed as the source image. How each
parameter is used remains the same, except:

 If the biCompression member of BITMAPINFOHEADER is BI_JPEG or BI_PNG,


lpBits points to a buffer containing a JPEG or PNG image, respectively. The
biSizeImage member of the BITMAPINFOHEADER structure specifies the size of
the buffer. The iUsage parameter must be set to DIB_RGB_COLORS. The dwRop
parameter must be set to SRCCOPY.
 To ensure proper metafile spooling while printing, applications must call the
CHECKJPEGFORMAT or CHECKPNGFORMAT escape to verify that the printer
recognizes the JPEG or PNG image, respectively, before calling StretchDIBits.

ICM: Color management is performed if color management has been enabled with a call to
SetICMMode with the iEnableICM parameter set to ICM_ON. If the bitmap specified by
lpBitsInfo has a BITMAPV4HEADER that specifies the gamma and endpoints members, or
a BITMAPV5HEADER that specifies either the gamma and endpoints members or the
profileData and profileSize members, then the call treats the bitmap's pixels as being
expressed in the color space described by those members, rather than in the device context's
source color space.

Examples

For an example, see Sizing a JPEG or PNG Image.

Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Wingdi.h (include Windows.h)
Library Gdi32.lib
DLL Gdi32.dll

d) SetViewportExtEx()
SetViewportExtEx Function

The SetViewportExtEx function sets the horizontal and vertical extents of the viewport for a
device context by using the specified values.

Syntax

Copy
BOOL SetViewportExtEx(
__in HDC hdc,
__in int nXExtent,
__in int nYExtent,
__out LPSIZE lpSize
);

Parameters

hdc [in]

A handle to the device context.

nXExtent [in]

The horizontal extent, in device units, of the viewport.

nYExtent [in]

The vertical extent, in device units, of the viewport.

lpSize [out]

A pointer to a SIZE structure that receives the previous viewport extents, in device
units. If lpSize is NULL, this parameter is not used.

Return Value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero.

Remarks
The viewport refers to the device coordinate system of the device space. The extent is the
maximum value of an axis. This function sets the maximum values for the horizontal and
vertical axes of the viewport in device coordinates (or pixels). When mapping between page
space and device space, SetWindowExtEx and SetViewportExtEx determine the scaling
factor between the window and the viewport. For more information, see Transformation of
Coordinate Spaces.

When the following mapping modes are set, calls to the SetWindowExtEx and
SetViewportExtEx functions are ignored.

 MM_HIENGLISH
 MM_HIMETRIC
 MM_LOENGLISH
 MM_LOMETRIC
 MM_TEXT
 MM_TWIPS

When MM_ISOTROPIC mode is set, an application must call the SetWindowExtEx


function before it calls SetViewportExtEx. Note that for the MM_ISOTROPIC mode certain
portions of a nonsquare screen may not be available for display because the logical units on
both axes represent equal physical distances.

Examples

For an example, see Invalidating the Client Area.

Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Wingdi.h (include Windows.h)
Library Gdi32.lib
DLL Gdi32.dll

e) SetScrollInfo()
SetScrollInfo Function

The SetScrollInfo function sets the parameters of a scroll bar, including the minimum and
maximum scrolling positions, the page size, and the position of the scroll box (thumb). The
function also redraws the scroll bar, if requested.

Syntax

Copy
int SetScrollInfo(
__in HWND hwnd,
__in int fnBar,
__in LPCSCROLLINFO lpsi,
__in BOOL fRedraw
);

Parameters

hwnd [in]
HWND

Handle to a scroll bar control or a window with a standard scroll bar, depending on
the value of the fnBar parameter.

fnBar [in]
int

Specifies the type of scroll bar for which to set parameters. This parameter can be one
of the following values.

Value Meaning
Sets the parameters of a scroll bar control. The hwnd parameter must be
SB_CTL
the handle to the scroll bar control.
SB_HORZ Sets the parameters of the window's standard horizontal scroll bar.
SB_VERT Sets the parameters of the window's standard vertical scroll bar.

lpsi [in]
LPCSCROLLINFO

Pointer to a SCROLLINFO structure. Before calling SetScrollInfo, set the cbSize


member of the structure to sizeof(SCROLLINFO), set the fMask member to indicate
the parameters to set, and specify the new parameter values in the appropriate
members.

The fMask member can be one or more of the following values.

Value Meaning
Disables the scroll bar instead of removing it, if the scroll
SIF_DISABLENOSCROLL
bar's new parameters make the scroll bar unnecessary.
Sets the scroll page to the value specified in the nPage
SIF_PAGE member of the SCROLLINFO structure pointed to by
lpsi.
Sets the scroll position to the value specified in the nPos
SIF_POS member of the SCROLLINFO structure pointed to by
lpsi.
Sets the scroll range to the value specified in the nMin
SIF_RANGE and nMax members of the SCROLLINFO structure
pointed to by lpsi.
 

fRedraw [in]
BOOL

Specifies whether the scroll bar is redrawn to reflect the changes to the scroll bar. If
this parameter is TRUE, the scroll bar is redrawn, otherwise, it is not redrawn.

Return Value

int

The return value is the current position of the scroll box.

Remarks

The SetScrollInfo function performs range checking on the values specified by the nPage
and nPos members of the SCROLLINFO structure. The nPage member must specify a
value from 0 to nMax - nMin +1. The nPos member must specify a value between nMin and
nMax - max( nPage– 1, 0). If either value is beyond its range, the function sets it to a value
that is just within the range.

If the fnBar parameter is SB_CTL and the window specified by the hwnd parameter is not a
system scroll bar control, the system sends the SBM_SETSCROLLINFO message to the
window to set scroll bar information (The system can optimize the message to
SBM_SETPOS or SBM_SETRANGE if the request is solely for the position or range). This
allows SetScrollInfo to operate on a custom control that mimics a scroll bar. If the window
does not handle SBM_SETSCROLLINFO (or the optimized SBM_SETPOS message or
SBM_SETRANGE message), then the SetScrollInfo function fails.

For an example, see Scrolling Text with the WM_PAINT Message.

Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Winuser.h (include Windows.h)
Library User32.lib
DLL User32.dll

f) CreateCompatibleDC()
CreateCompatibleDC Function

The CreateCompatibleDC function creates a memory device context (DC) compatible with
the specified device.

Syntax
Copy
HDC CreateCompatibleDC(
__in HDC hdc
);

Parameters

hdc [in]

A handle to an existing DC. If this handle is NULL, the function creates a memory
DC compatible with the application's current screen.

Return Value

If the function succeeds, the return value is the handle to a memory DC.

If the function fails, the return value is NULL.

Remarks

A memory DC exists only in memory. When the memory DC is created, its display surface is
exactly one monochrome pixel wide and one monochrome pixel high. Before an application
can use a memory DC for drawing operations, it must select a bitmap of the correct width and
height into the DC. To select a bitmap into a DC, use the CreateCompatibleBitmap
function, specifying the height, width, and color organization required.

When a memory DC is created, all attributes are set to normal default values. The memory
DC can be used as a normal DC. You can set the attributes; obtain the current settings of its
attributes; and select pens, brushes, and regions.

The CreateCompatibleDC function can only be used with devices that support raster
operations. An application can determine whether a device supports these operations by
calling the GetDeviceCaps function.

When you no longer need the memory DC, call the DeleteDC function.

If hdc is NULL, the thread that calls CreateCompatibleDC owns the HDC that is created.
When this thread is destroyed, the HDC is no longer valid. Thus, if you create the HDC
andpass it to another thread, then exit the first thread, the second thread will not be able to use
the HDC.

ICM: If the DC that is passed to this function is enabled for Image Color Management
(ICM), the DC created by the function is ICM-enabled. The source and destination color
spaces are specified in the DC.

Examples

For an example, see Capturing an Image.


Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Wingdi.h (include Windows.h)
Library Gdi32.lib
DLL Gdi32.dll

12. What will be the result of following lines of code?


Case WM_LBUTTONDOWN:
HBITMAP hBitmap;
HMENU hMenu;
hBitmap = LoadBitMap(hInstance, MAKEINTRESOURCE(IDB_BMP));
hMenu = GetSystemMenu(hwnd, FALSE);
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_BITMAP, IDM_BITMAP, hBitmap);
Return 0;
13. Write the pseudo code for your own function MyTranslateMessage() that replaces system’s
API
TranslateMessage().

TranslateMessage Function

The TranslateMessage function translates virtual-key messages into character messages. The
character messages are posted to the calling thread's message queue, to be read the next time
the thread calls the GetMessage or PeekMessage function.

Syntax

Copy
BOOL TranslateMessage(
__in const MSG *lpMsg
);

Parameters

lpMsg [in]
MSG

Pointer to an MSG structure that contains message information retrieved from the
calling thread's message queue by using the GetMessage or PeekMessage function.

Return Value

BOOL
If the message is translated (that is, a character message is posted to the thread's message
queue), the return value is nonzero.

If the message is WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, or


WM_SYSKEYUP, the return value is nonzero, regardless of the translation.

If the message is not translated (that is, a character message is not posted to the thread's
message queue), the return value is zero.

Remarks

The TranslateMessage function does not modify the message pointed to by the lpMsg
parameter.

WM_KEYDOWN and WM_KEYUP combinations produce a WM_CHAR or


WM_DEADCHAR message. WM_SYSKEYDOWN and WM_SYSKEYUP combinations
produce a WM_SYSCHAR or WM_SYSDEADCHAR message.

TranslateMessage produces WM_CHAR messages only for keys that are mapped to ASCII
characters by the keyboard driver.

If applications process virtual-key messages for some other purpose, they should not call
TranslateMessage. For instance, an application should not call TranslateMessage if the
TranslateAccelerator function returns a nonzero value. Note that the application is
responsible for retrieving and dispatching input messages to the dialog box. Most
applications use the main message loop for this. However, to permit the user to move to and
to select controls by using the keyboard, the application must call IsDialogMessage. For
more information, see Dialog Box Keyboard Interface.

Examples

14. A DllMain() function has this declaration :-


int CALLBACK DllMain(HINSTANCE hInstance, DWORD dwReason, PVOID pReserved)
What is contained in dwReason and how it can be used?

DllMain Callback Function

An optional entry point into a dynamic-link library (DLL). When the system starts or
terminates a process or thread, it calls the entry-point function for each loaded DLL using the
first thread of the process. The system also calls the entry-point function for a DLL when it is
loaded or unloaded using the LoadLibrary and FreeLibrary functions.

Warning  There are serious limits on what you can do in a DLL entry point. To provide more
complex initialization, create an initialization routine for the DLL. You can require
applications to call the initialization routine before calling any other routines in the DLL.
Syntax

VB
C#
C++
F#
JScript
Copy
BOOL WINAPI DllMain(
__in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved
);

Parameters

hinstDLL [in]

A handle to the DLL module. The value is the base address of the DLL. The
HINSTANCE of a DLL is the same as the HMODULE of the DLL, so hinstDLL can
be used in calls to functions that require a module handle.

fdwReason [in]

The reason code that indicates why the DLL entry-point function is being called. This
parameter can be one of the following values.

Value Meaning
The DLL is being loaded into the virtual address space of
the current process as a result of the process starting up or
as a result of a call to LoadLibrary. DLLs can use this
opportunity to initialize any instance data or to use the
DLL_PROCESS_ATTACH
TlsAlloc function to allocate a thread local storage (TLS)
1
index.

The lpReserved parameter indicates whether the DLL is


being loaded statically or dynamically.
DLL_PROCESS_DETACH The DLL is being unloaded from the virtual address
0 space of the calling process because it was loaded
unsuccessfully or the reference count has reached zero
(the processes has either terminated or called
FreeLibrary one time for each time it called
LoadLibrary).

The lpReserved parameter indicates whether the DLL is


being unloaded as a result of a FreeLibrary call, a
failure to load, or process termination.

The DLL can use this opportunity to call the TlsFree


function to free any TLS indices allocated by using
TlsAlloc and to free any thread local data.

Note that the thread that receives the


DLL_PROCESS_DETACH notification is not
necessarily the same thread that received the
DLL_PROCESS_ATTACH notification.
The current process is creating a new thread. When this
occurs, the system calls the entry-point function of all
DLLs currently attached to the process. The call is made
in the context of the new thread. DLLs can use this
opportunity to initialize a TLS slot for the thread. A
thread calling the DLL entry-point function with
DLL_THREAD_ATTACH DLL_PROCESS_ATTACH does not call the DLL entry-
2 point function with DLL_THREAD_ATTACH.

Note that a DLL's entry-point function is called with this


value only by threads created after the DLL is loaded by
the process. When a DLL is loaded using LoadLibrary,
existing threads do not call the entry-point function of the
newly loaded DLL.
A thread is exiting cleanly. If the DLL has stored a
pointer to allocated memory in a TLS slot, it should use
DLL_THREAD_DETACH this opportunity to free the memory. The system calls the
3 entry-point function of all currently loaded DLLs with
this value. The call is made in the context of the exiting
thread.

lpvReserved [in]

If fdwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads


and non-NULL for static loads.

If fdwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if FreeLibrary


has been called or the DLL load failed and non-NULL if the process is terminating.

Return Value

When the system calls the DllMain function with the DLL_PROCESS_ATTACH value, the
function returns TRUE if it succeeds or FALSE if initialization fails. If the return value is
FALSE when DllMain is called because the process uses the LoadLibrary function,
LoadLibrary returns NULL. (The system immediately calls your entry-point function with
DLL_PROCESS_DETACH and unloads the DLL.) If the return value is FALSE when
DllMain is called during process initialization, the process terminates with an error. To get
extended error information, call GetLastError.
When the system calls the DllMain function with any value other than
DLL_PROCESS_ATTACH, the return value is ignored.

Remarks

DllMain is a placeholder for the library-defined function name. You must specify the actual
name you use when you build your DLL. For more information, see the documentation
included with your development tools.

During initial process startup or after a call to LoadLibrary, the system scans the list of
loaded DLLs for the process. For each DLL that has not already been called with the
DLL_PROCESS_ATTACH value, the system calls the DLL's entry-point function. This call
is made in the context of the thread that caused the process address space to change, such as
the primary thread of the process or the thread that called LoadLibrary. Access to the entry
point is serialized by the system on a process-wide basis. Threads in DllMain hold the loader
lock so no additional DLLs can be dynamically loaded or initialized.

If the DLL's entry-point function returns FALSE following a DLL_PROCESS_ATTACH


notification, it receives a DLL_PROCESS_DETACH notification and the DLL is unloaded
immediately. However, if the DLL_PROCESS_ATTACH code throws an exception, the
entry-point function will not receive the DLL_PROCESS_DETACH notification.

There are cases in which the entry-point function is called for a terminating thread even if the
entry-point function was never called with DLL_THREAD_ATTACH for the thread:

 The thread was the initial thread in the process, so the system called the entry-point
function with the DLL_PROCESS_ATTACH value.
 The thread was already running when a call to the LoadLibrary function was made,
so the system never called the entry-point function for it.

When a DLL is unloaded from a process as a result of an unsuccessful load of the DLL,
termination of the process, or a call to FreeLibrary, the system does not call the DLL's
entry-point function with the DLL_THREAD_DETACH value for the individual threads of
the process. The DLL is only sent a DLL_PROCESS_DETACH notification. DLLs can take
this opportunity to clean up all resources for all threads known to the DLL.

When handling DLL_PROCESS_DETACH, a DLL should free resources such as heap


memory only if the DLL is being unloaded dynamically (the lpReserved parameter is NULL).
If the process is terminating (the lpvReserved parameter is non-NULL), all threads in the
process except the current thread either have exited already or have been explicitly
terminated by a call to the ExitProcess function, which might leave some process resources
such as heaps in an inconsistent state. In this case, it is not safe for the DLL to clean up the
resources. Instead, the DLL should allow the operating system to reclaim the memory.

If you terminate a process by calling TerminateProcess or TerminateJobObject, the DLLs


of that process do not receive DLL_PROCESS_DETACH notifications. If you terminate a
thread by calling TerminateThread, the DLLs of that thread do not receive
DLL_THREAD_DETACH notifications.
The entry-point function should perform only simple initialization or termination tasks. It
must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these
functions), because this may create dependency loops in the DLL load order. This can result
in a DLL being used before the system has executed its initialization code. Similarly, the
entry-point function must not call the FreeLibrary function (or a function that calls
FreeLibrary) during process termination, because this can result in a DLL being used after
the system has executed its termination code.

Because Kernel32.dll is guaranteed to be loaded in the process address space when the entry-
point function is called, calling functions in Kernel32.dll does not result in the DLL being
used before its initialization code has been executed. Therefore, the entry-point function can
call functions in Kernel32.dll that do not load other DLLs. For example, DllMain can create
synchronization objects such as critical sections and mutexes, and use TLS. Unfortunately,
there is not a comprehensive list of safe functions in Kernel32.dll.

Windows 2000:  Do not create a named synchronization object in DllMain because the


system will then load an additional DLL.

Calling functions that require DLLs other than Kernel32.dll may result in problems that are
difficult to diagnose. For example, calling User, Shell, and COM functions can cause access
violation errors, because some functions load other system components. Conversely, calling
functions such as these during termination can cause access violation errors because the
corresponding component may already have been unloaded or uninitialized.

Because DLL notifications are serialized, entry-point functions should not attempt to
communicate with other threads or processes. Deadlocks may occur as a result.

For information on best practices when writing a DLL, see


http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx.

If your DLL is linked with the C run-time library (CRT), the entry point provided by the CRT
calls the constructors and destructors for global and static C++ objects. Therefore, these
restrictions for DllMain also apply to constructors and destructors and any code that is called
from them.

Examples

For an example, see Dynamic-Link Library Entry-Point Function.

Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server

15. CenterHorz() is a user defined function to center a given string in a given row on the client
area of a given
window. Its declaration is as follows -
void CenterHorz(HWND, int, char *);
Implement it.
16. Write the steps required to use accelerators in your application. *
17. How can you utilise the idle time of your application? Which portion of your code will you alter
to achieve this? Write the portion of the code, which will undergo change.

18. Write in brief the steps required to


create a DLL. *

19. Explain the purpose and use of the API CreateThread().

CreateThread()
CreateThread Function

Creates a thread to execute within the virtual address space of the calling process.

To create a thread that runs in the virtual address space of another process, use the
CreateRemoteThread function.

Syntax

VB
C#
C++
F#
JScript
Copy
HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId
);

Parameters

lpThreadAttributes [in, optional]

A pointer to a SECURITY_ATTRIBUTES structure that determines whether the


returned handle can be inherited by child processes. If lpThreadAttributes is NULL,
the handle cannot be inherited.

The lpSecurityDescriptor member of the structure specifies a security descriptor for


the new thread. If lpThreadAttributes is NULL, the thread gets a default security
descriptor. The ACLs in the default security descriptor for a thread come from the
primary token of the creator.

Windows XP/2000:  The ACLs in the default security descriptor for a thread


come from the primary or impersonation token of the creator. This behavior
changed with Windows XP with SP2 and Windows Server 2003. For more
information, see Remarks.
dwStackSize [in]

The initial size of the stack, in bytes. The system rounds this value to the nearest page.
If this parameter is zero, the new thread uses the default size for the executable. For
more information, see Thread Stack Size.

lpStartAddress [in]

A pointer to the application-defined function to be executed by the thread. This


pointer represents the starting address of the thread. For more information on the
thread function, see ThreadProc.

lpParameter [in, optional]

A pointer to a variable to be passed to the thread.

dwCreationFlags [in]

The flags that control the creation of the thread.

Value Meaning
0 The thread runs immediately after creation.
The thread is created in a suspended state,
CREATE_SUSPENDED
and does not run until the ResumeThread
0x00000004
function is called.
The dwStackSize parameter specifies the
initial reserve size of the stack. If this flag
is not specified, dwStackSize specifies the
STACK_SIZE_PARAM_IS_A_RESERV commit size.
ATION
0x00010000 Windows 2000:  The
STACK_SIZE_PARAM_IS_A_RESERV
ATION flag is not supported.

lpThreadId [out, optional]

A pointer to a variable that receives the thread identifier. If this parameter is NULL,
the thread identifier is not returned.

Return Value

If the function succeeds, the return value is a handle to the new thread.

If the function fails, the return value is NULL. To get extended error information, call
GetLastError.
Note that CreateThread may succeed even if lpStartAddress points to data, code, or is not
accessible. If the start address is invalid when the thread runs, an exception occurs, and the
thread terminates. Thread termination due to a invalid start address is handled as an error exit
for the thread's process. This behavior is similar to the asynchronous nature of
CreateProcess, where the process is created even if it refers to invalid or missing dynamic-
link libraries (DLLs).

Remarks

The number of threads a process can create is limited by the available virtual memory. By
default, every thread has one megabyte of stack space. Therefore, you can create at most
2,048 threads. If you reduce the default stack size, you can create more threads. However,
your application will have better performance if you create one thread per processor and build
queues of requests for which the application maintains the context information. A thread
would process all requests in a queue before processing requests in the next queue.

The new thread handle is created with the THREAD_ALL_ACCESS access right. If a
security descriptor is not provided when the thread is created, a default security descriptor is
constructed for the new thread using the primary token of the process that is creating the
thread. When a caller attempts to access the thread with the OpenThread function, the
effective token of the caller is evaluated against this security descriptor to grant or deny
access.

Windows XP/2000:  If a security descriptor is not provided when the thread is created, a


default security descriptor is constructed using the effective token of the thread. If the thread
is impersonating another user, the thread's effective token is the impersonation token and the
default security descriptor allows access only to the impersonation token's TokenDefaultDacl
owner or members. If the thread is not impersonating another user, the thread's effective
token is its primary token. This behavior changed starting with Windows XP with SP2 and
Windows Server 2003. For more information, see Thread Security and Access Rights.

The newly created thread has full access rights to itself when calling the GetCurrentThread
function.

Windows Server 2003 and Windows XP/2000:  The thread's access rights to itself are


computed by evaluating the primary token of the process in which the thread was created
against the default security descriptor constructed for the thread. If the thread is created in a
remote process, the primary token of the remote process is used. As a result, the newly
created thread may have reduced access rights to itself when calling GetCurrentThread.
Some access rights including THREAD_SET_THREAD_TOKEN and
THREAD_GET_CONTEXT may not be present, leading to unexpected failures. For this
reason, creating a thread while impersonating another user is not recommended.

The thread execution begins at the function specified by the lpStartAddress parameter. If this
function returns, the DWORD return value is used to terminate the thread in an implicit call
to the ExitThread function. Use the GetExitCodeThread function to get the thread's return
value.
The thread is created with a thread priority of THREAD_PRIORITY_NORMAL. Use the
GetThreadPriority and SetThreadPriority functions to get and set the priority value of a
thread.

When a thread terminates, the thread object attains a signaled state, satisfying any threads that
were waiting on the object.

The thread object remains in the system until the thread has terminated and all handles to it
have been closed through a call to CloseHandle.

The ExitProcess, ExitThread, CreateThread, CreateRemoteThread functions, and a


process that is starting (as the result of a call by CreateProcess) are serialized between each
other within a process. Only one of these events can happen in an address space at a time.
This means that the following restrictions hold:

 During process startup and DLL initialization routines, new threads can be created,
but they do not begin execution until DLL initialization is done for the process.
 Only one thread in a process can be in a DLL initialization or detach routine at a time.
 ExitProcess does not complete until there are no threads in their DLL initialization or
detach routines.

A thread in an executable that calls the C run-time library (CRT) should use the
_beginthreadex and _endthreadex functions for thread management rather than
CreateThread and ExitThread; this requires the use of the multi-threaded version of the
CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the
process in low-memory conditions.

Examples

For an example, see Creating Threads.

Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Winbase.h (include Windows.h)
Library Kernel32.lib
DLL Kernel32.dll

20. Explain with example the purpose and use of the following APIs/structures/messages:
a. SetDIBitsToDevice()

SetDIBitsToDevice Function
The SetDIBitsToDevice function sets the pixels in the specified rectangle on the device that
is associated with the destination device context using color data from a DIB, JPEG, or PNG
image.

Syntax

Copy
int SetDIBitsToDevice(
__in HDC hdc,
__in int XDest,
__in int YDest,
__in DWORD dwWidth,
__in DWORD dwHeight,
__in int XSrc,
__in int YSrc,
__in UINT uStartScan,
__in UINT cScanLines,
__in const VOID *lpvBits,
__in const BITMAPINFO *lpbmi,
__in UINT fuColorUse
);

Parameters

hdc [in]

A handle to the device context.

XDest [in]

The x-coordinate, in logical units, of the upper-left corner of the destination rectangle.

YDest [in]

The y-coordinate, in logical units, of the upper-left corner of the destination rectangle.

dwWidth [in]

The width, in logical units, of the image.

dwHeight [in]

The height, in logical units, of the image.

XSrc [in]

The x-coordinate, in logical units, of the lower-left corner of the image.

YSrc [in]

The y-coordinate, in logical units, of the lower-left corner of the image.


uStartScan [in]

The starting scan line in the image.

cScanLines [in]

The number of DIB scan lines contained in the array pointed to by the lpvBits
parameter.

lpvBits [in]

A pointer to the color data stored as an array of bytes. For more information, see the
following Remarks section.

lpbmi [in]

A pointer to a BITMAPINFO structure that contains information about the DIB.

fuColorUse [in]

Indicates whether the bmiColors member of the BITMAPINFO structure contains


explicit red, green, blue (RGB) values or indexes into a palette. For more information,
see the following Remarks section.

The fuColorUse parameter must be one of the following values.

Value Meaning
The color table consists of an array of 16-bit indexes into the
DIB_PAL_COLORS
currently selected logical palette.
DIB_RGB_COLORS The color table contains literal RGB values.

Return Value

If the function succeeds, the return value is the number of scan lines set.

If zero scan lines are set (such as when dwHeight is 0) or the function fails, the function
returns zero.

If the driver cannot support the JPEG or PNG file image passed to SetDIBitsToDevice, the
function will fail and return GDI_ERROR. If failure does occur, the application must fall
back on its own JPEG or PNG support to decompress the image into a bitmap, and then pass
the bitmap to SetDIBitsToDevice.

Remarks

Optimal bitmap drawing speed is obtained when the bitmap bits are indexes into the system
palette.
Applications can retrieve the system palette colors and indexes by calling the
GetSystemPaletteEntries function. After the colors and indexes are retrieved, the
application can create the DIB. For more information about the system palette, see Colors.

The scan lines must be aligned on a DWORD except for RLE-compressed bitmaps.

The origin of a bottom-up DIB is the lower-left corner of the bitmap; the origin of a top-down
DIB is the upper-left corner.

To reduce the amount of memory required to set bits from a large DIB on a device surface, an
application can band the output by repeatedly calling SetDIBitsToDevice, placing a different
portion of the bitmap into the lpvBits array each time. The values of the uStartScan and
cScanLines parameters identify the portion of the bitmap contained in the lpvBits array.

The SetDIBitsToDevice function returns an error if it is called by a process that is running in


the background while a full-screen MS-DOS session runs in the foreground.

 If the biCompression member of BITMAPINFOHEADER is BI_JPEG or BI_PNG,


lpvBits points to a buffer containing a JPEG or PNG image. The biSizeImage
member of specifies the size of the buffer. The fuColorUse parameter must be set to
DIB_RGB_COLORS.
 To ensure proper metafile spooling while printing, applications must call the
CHECKJPEGFORMAT or CHECKPNGFORMAT escape to verify that the printer
recognizes the JPEG or PNG image, respectively, before calling SetDIBitsToDevice.

ICM: Color management is performed if color management has been enabled with a call to
SetICMMode with the iEnableICM parameter set to ICM_ON. If the bitmap specified by
lpbmi has a BITMAPV4HEADER that specifies the gamma and endpoints members, or a
BITMAPV5HEADER that specifies either the gamma and endpoints members or the
profileData and profileSize members, then the call treats the bitmap's pixels as being
expressed in the color space described by those members, rather than in the device context's
source color space.

Examples

For an example, see Testing a Printer for JPEG or PNG Support.

Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Wingdi.h (include Windows.h)
Library Gdi32.lib
DLL Gdi32.dll
b. EnterCriticalSection()
WE ALSO HEAVE
DeleteCriticalSection Function

Releases all resources used by an unowned critical section object.

Syntax

VB
C#
C++
F#
JScript
Copy
void WINAPI DeleteCriticalSection(
__inout LPCRITICAL_SECTION lpCriticalSection
);

Parameters

lpCriticalSection [in, out]

A pointer to the critical section object. The object must have been previously
initialized with the InitializeCriticalSection function.

Return Value

This function does not return a value.

Remarks

Deleting a critical section object releases all system resources used by the object.

After a critical section object has been deleted, do not reference the object in any function
that operates on critical sections (such as EnterCriticalSection, TryEnterCriticalSection,
and LeaveCriticalSection) other than InitializeCriticalSection and
InitializeCriticalSectionAndSpinCount. If you attempt to do so, memory corruption and
other unexpected errors can occur.

If a critical section is deleted while it is still owned, the state of the threads waiting for
ownership of the deleted critical section is undefined.

Examples

For an example that uses DeleteCriticalSection, see Using Critical Section Objects.
Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Winbase.h (include Windows.h)
Library Kernel32.lib
DLL Kernel32.dll

EnterCriticalSection Function

Waits for ownership of the specified critical section object. The function returns when the
calling thread is granted ownership.

Syntax

VB
C#
C++
F#
JScript
Copy
void WINAPI EnterCriticalSection(
__inout LPCRITICAL_SECTION lpCriticalSection
);

Parameters

lpCriticalSection [in, out]

A pointer to the critical section object.

Return Value

This function does not return a value.

This function can raise EXCEPTION_POSSIBLE_DEADLOCK if a wait operation on the


critical section times out. The timeout interval is specified by the following registry value:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\CriticalSectionTimeout. Do not handle a possible deadlock exception; instead,
debug the application.

Windows 2000:  In low memory situations, EnterCriticalSection can raise an exception. Do


not attempt to handle this exception; instead, either terminate the process or allow the
exception to pass to the unhandled exception filter. To avoid an exception due to low
memory, call the InitializeCriticalSectionAndSpinCount function to preallocate the event
used by EnterCriticalSection instead of calling the InitializeCriticalSection function,
which forces EnterCriticalSection to allocate the event. Preallocating the event is not
necessary on Windows XP or later because EnterCriticalSection is guaranteed not to fail
due to lack of resources.

Remarks

The threads of a single process can use a critical section object for mutual-exclusion
synchronization. The process is responsible for allocating the memory used by a critical
section object, which it can do by declaring a variable of type CRITICAL_SECTION.
Before using a critical section, some thread of the process must call InitializeCriticalSection
or InitializeCriticalSectionAndSpinCount to initialize the object.

To enable mutually exclusive access to a shared resource, each thread calls the
EnterCriticalSection or TryEnterCriticalSection function to request ownership of the
critical section before executing any section of code that accesses the protected resource. The
difference is that TryEnterCriticalSection returns immediately, regardless of whether it
obtained ownership of the critical section, while EnterCriticalSection blocks until the thread
can take ownership of the critical section. When it has finished executing the protected code,
the thread uses the LeaveCriticalSection function to relinquish ownership, enabling another
thread to become owner and access the protected resource. There is no guarantee about the
order in which waiting threads will acquire ownership of the critical section.

After a thread has ownership of a critical section, it can make additional calls to
EnterCriticalSection or TryEnterCriticalSection without blocking its execution. This
prevents a thread from deadlocking itself while waiting for a critical section that it already
owns. The thread enters the critical section each time EnterCriticalSection and
TryEnterCriticalSection succeed. A thread must call LeaveCriticalSection once for each
time that it entered the critical section.

Any thread of the process can use the DeleteCriticalSection function to release the system
resources that were allocated when the critical section object was initialized. After this
function has been called, the critical section object can no longer be used for synchronization.

If a thread terminates while it has ownership of a critical section, the state of the critical
section is undefined.

If a critical section is deleted while it is still owned, the state of the threads waiting for
ownership of the deleted critical section is undefined.

Examples

For an example that uses EnterCriticalSection, see Using Critical Section Objects.

Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Winbase.h (include Windows.h)
Library Kernel32.lib
DLL Kernel32.dll

c. WaitForMultipleObjects()

WaitForMultipleObjects Function

Waits until one or all of the specified objects are in the signaled state or the time-out interval
elapses.

To enter an alertable wait state, use the WaitForMultipleObjectsEx function.

Syntax

VB
C#
C++
F#
JScript
Copy
DWORD WINAPI WaitForMultipleObjects(
__in DWORD nCount,
__in const HANDLE *lpHandles,
__in BOOL bWaitAll,
__in DWORD dwMilliseconds
);

Parameters

nCount [in]

The number of object handles in the array pointed to by lpHandles. The maximum
number of object handles is MAXIMUM_WAIT_OBJECTS.

lpHandles [in]

An array of object handles. For a list of the object types whose handles can be
specified, see the following Remarks section. The array can contain handles to objects
of different types. It may not contain multiple copies of the same handle.

If one of these handles is closed while the wait is still pending, the function's behavior
is undefined.

The handles must have the SYNCHRONIZE access right. For more information, see
Standard Access Rights.

bWaitAll [in]
If this parameter is TRUE, the function returns when the state of all objects in the
lpHandles array is signaled. If FALSE, the function returns when the state of any one
of the objects is set to signaled. In the latter case, the return value indicates the object
whose state caused the function to return.

dwMilliseconds [in]

The time-out interval, in milliseconds. If a nonzero value is specified, the function


waits until the specified objects are signaled or the interval elapses. If dwMilliseconds
is zero, the function does not enter a wait state if the specified objects are not
signaled; it always returns immediately. If dwMilliseconds is INFINITE, the function
will return only when the specified objects are signaled.

Return Value

If the function succeeds, the return value indicates the event that caused the function to
return. It can be one of the following values. (Note that WAIT_OBJECT_0 is defined as 0
and WAIT_ABANDONED_0 is defined as 0x00000080L.)

Return code/value Description


If bWaitAll is TRUE, the return value indicates that the state
of all specified objects is signaled.

WAIT_OBJECT_0 to If bWaitAll is FALSE, the return value minus


(WAIT_OBJECT_0 + nCount– WAIT_OBJECT_0 indicates the lpHandles array index of
1) the object that satisfied the wait. If more than one object
became signaled during the call, this is the array index of the
signaled object with the smallest index value of all the
signaled objects.
If bWaitAll is TRUE, the return value indicates that the state
of all specified objects is signaled and at least one of the
objects is an abandoned mutex object.

If bWaitAll is FALSE, the return value minus


WAIT_ABANDONED_0 to
WAIT_ABANDONED_0 indicates the lpHandles array
(WAIT_ABANDONED_0 +
index of an abandoned mutex object that satisfied the wait.
nCount– 1)
Ownership of the mutex object is granted to the calling
thread, and the mutex is set to nonsignaled.

If a mutex was protecting persistent state information, you


should check it for consistency.
WAIT_TIMEOUT The time-out interval elapsed and the conditions specified by
0x00000102L the bWaitAll parameter are not satisfied.
WAIT_FAILED The function has failed. To get extended error information,
(DWORD)0xFFFFFFFF call GetLastError.

Remarks
The WaitForMultipleObjects function determines whether the wait criteria have been met.
If the criteria have not been met, the calling thread enters the wait state until the conditions of
the wait criteria have been met or the time-out interval elapses.

When bWaitAll is TRUE, the function's wait operation is completed only when the states of
all objects have been set to signaled. The function does not modify the states of the specified
objects until the states of all objects have been set to signaled. For example, a mutex can be
signaled, but the thread does not get ownership until the states of the other objects are also set
to signaled. In the meantime, some other thread may get ownership of the mutex, thereby
setting its state to nonsignaled.

When bWaitAll is FALSE, this function checks the handles in the array in order starting with
index 0, until one of the objects is signaled. If multiple objects become signaled, the function
returns the index of the first handle in the array whose object was signaled.

The function modifies the state of some types of synchronization objects. Modification
occurs only for the object or objects whose signaled state caused the function to return. For
example, the count of a semaphore object is decreased by one. For more information, see the
documentation for the individual synchronization objects.

To wait on more than MAXIMUM_WAIT_OBJECTS handles, use one of the following


methods:

 Create a thread to wait on MAXIMUM_WAIT_OBJECTS handles, then wait on that


thread plus the other handles. Use this technique to break the handles into groups of
MAXIMUM_WAIT_OBJECTS.
 Call RegisterWaitForSingleObject to wait on each handle. A wait thread from the
thread pool waits on MAXIMUM_WAIT_OBJECTS registered objects and assigns a
worker thread after the object is signaled or the time-out interval expires.

The WaitForMultipleObjects function can specify handles of any of the following object
types in the lpHandles array:

 Change notification
 Console input
 Event
 Memory resource notification
 Mutex
 Process
 Semaphore
 Thread
 Waitable timer

Use caution when calling the wait functions and code that directly or indirectly creates
windows. If a thread creates any windows, it must process messages. Message broadcasts are
sent to all windows in the system. A thread that uses a wait function with no time-out interval
may cause the system to become deadlocked. Two examples of code that indirectly creates
windows are DDE and the CoInitialize function. Therefore, if you have a thread that creates
windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather
than WaitForMultipleObjects.

Examples

Waiting for Multiple Objects

The following example uses the CreateEvent function to create two event objects and the
CreateThread function to create a thread. It then uses the WaitForMultipleObjects
function to wait for the thread to set the state of one of the objects to signaled using the
SetEvent function.

For an example that waits for a single object, see Using Mutex Objects.

Copy
#include <windows.h>
#include <stdio.h>

HANDLE ghEvents[2];

DWORD WINAPI ThreadProc( LPVOID );

void main()
{
HANDLE hThread;
DWORD i, dwEvent, dwThreadID;

// Create two event objects

for (i = 0; i < 2; i++)


{
ghEvents[i] = CreateEvent(
NULL, // default security attributes
FALSE, // auto-reset event object
FALSE, // initial state is nonsignaled
NULL); // unnamed object

if (ghEvents[i] == NULL)
{
printf("CreateEvent error: %d\n", GetLastError() );
ExitProcess(0);
}
}

// Create a thread

hThread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&dwThreadID); // receive thread identifier

if( hThread == NULL )


{
printf("CreateThread error: %d\n", GetLastError());
return;
}

// Wait for the thread to signal one of the event objects

dwEvent = WaitForMultipleObjects(
2, // number of objects in array
ghEvents, // array of objects
FALSE, // wait for any object
5000); // five-second wait

// The return value indicates which event is signaled

switch (dwEvent)
{
// ghEvents[0] was signaled
case WAIT_OBJECT_0 + 0:
// TODO: Perform tasks required by this event
printf("First event was signaled.\n");
break;

// ghEvents[1] was signaled


case WAIT_OBJECT_0 + 1:
// TODO: Perform tasks required by this event
printf("Second event was signaled.\n");
break;

case WAIT_TIMEOUT:
printf("Wait timed out.\n");
break;

// Return value is invalid.


default:
printf("Wait error: %d\n", GetLastError());
ExitProcess(0);
}

// Close event handles

for (i = 0; i < 2; i++)


CloseHandle(ghEvents[i]);
}

DWORD WINAPI ThreadProc( LPVOID lpParam )


{
// Set one event to the signaled state

if ( !SetEvent(ghEvents[0]) )
{
printf("SetEvent failed (%d)\n", GetLastError());
return -1;
}
return 1;
}

d. NMHDR

NMHDR Structure
Contains information about a notification message.

Syntax

Copy
typedef struct tagNMHDR {
HWND hwndFrom;
UINT_PTR idFrom;
UINT code;
} NMHDR;

Members

hwndFrom
HWND

A window handle to the control sending the message.

idFrom
UINT_PTR

An identifier of the control sending the message.

code
UINT

A notification code. This member can be one of the common notification codes (see
Notifications under General Control Reference), or it can be a control-specific
notification code.

Requirements

Minimum supported client Windows 2000 Professional


Minimum supported server Windows 2000 Server
Header Winuser.h

e. WM_RENDERFORMAT

WM_RENDERFORMAT Message

The WM_RENDERFORMAT message is sent to the clipboard owner if it has delayed


rendering a specific clipboard format and if an application has requested data in that format.
The clipboard owner must render data in the specified format and place it on the clipboard by
calling the SetClipboardData function.
Parameters

wParam

Specifies the clipboard format to be rendered.

lParam

This parameter is not used.

Return Value

If an application processes this message, it should return zero.

Remarks

When responding to a WM_RENDERFORMAT message, the clipboard owner must not


open the clipboard before calling SetClipboardData.

Requirements

Minimum supported client Windows XP


Minimum supported server Windows 2000 Server
Header Winuser.h (include Windows.h)

You might also like