- GUI
- Windows API tutorial
- Introduction to Windows API
- Windows API main functions
- System functions in Windows API
- Strings in Windows API
- Date & time in Windows API
- A window in Windows API
- First steps in UI
- Windows API menus
- Windows API dialogs
- Windows API controls I
- Windows API controls II
- Windows API controls III
- Advanced controls in Windows API
- Custom controls in Windows API
- The GDI in Windows API
- PyQt4 tutorial
- PyQt5 tutorial
- Qt4 tutorial
- Introduction to Qt4 toolkit
- Qt4 utility classes
- Strings in Qt4
- Date and time in Qt4
- Working with files and directories in Qt4
- First programs in Qt4
- Menus and toolbars in Qt4
- Layout management in Qt4
- Events and signals in Qt4
- Qt4 Widgets
- Qt4 Widgets II
- Painting in Qt4
- Custom widget in Qt4
- The Breakout game in Qt4
- Qt5 tutorial
- Introduction to Qt5 toolkit
- Strings in Qt5
- Date and time in Qt5
- Containers in Qt5
- Working with files and directories in Qt5
- First programs in Qt5
- Menus and toolbars in Qt5
- Layout management in Qt5
- Events and signals in Qt5
- Qt5 Widgets
- Qt5 Widgets II
- Painting in Qt5
- Custom widget in Qt5
- Snake in Qt5
- The Breakout game in Qt5
- PySide tutorial
- Tkinter tutorial
- Tcl/Tk tutorial
- Qt Quick tutorial
- Java Swing tutorial
- JavaFX tutorial
- Java SWT tutorial
- wxWidgets tutorial
- Introduction to wxWidgets
- wxWidgets helper classes
- First programs in wxWidgets
- Menus and toolbars in wxWidgets
- Layout management in wxWidgets
- Events in wxWidgets
- Dialogs in wxWidgets
- wxWidgets widgets
- wxWidgets widgets II
- Drag and Drop in wxWidgets
- Device Contexts in wxWidgets
- Custom widgets in wxWidgets
- The Tetris game in wxWidgets
- wxPython tutorial
- Introduction to wxPython
- First Steps
- Menus and toolbars
- Layout management in wxPython
- Events in wxPython
- wxPython dialogs
- Widgets
- Advanced widgets in wxPython
- Drag and drop in wxPython
- Internationalisation
- Application skeletons in wxPython
- The GDI
- Mapping modes
- Creating custom widgets
- Tips and Tricks
- wxPython Gripts
- The Tetris game in wxPython
- C# Winforms Mono tutorial
- Java Gnome tutorial
- Introduction to Java Gnome
- First steps in Java Gnome
- Layout management in Java Gnome
- Layout management II in Java Gnome
- Menus in Java Gnome
- Toolbars in Java Gnome
- Events in Java Gnome
- Widgets in Java Gnome
- Widgets II in Java Gnome
- Advanced widgets in Java Gnome
- Dialogs in Java Gnome
- Pango in Java Gnome
- Drawing with Cairo in Java Gnome
- Drawing with Cairo II
- Nibbles in Java Gnome
- QtJambi tutorial
- GTK+ tutorial
- Ruby GTK tutorial
- GTK# tutorial
- Visual Basic GTK# tutorial
- PyGTK tutorial
- Introduction to PyGTK
- First steps in PyGTK
- Layout management in PyGTK
- Menus in PyGTK
- Toolbars in PyGTK
- Signals & events in PyGTK
- Widgets in PyGTK
- Widgets II in PyGTK
- Advanced widgets in PyGTK
- Dialogs in PyGTK
- Pango
- Pango II
- Drawing with Cairo in PyGTK
- Drawing with Cairo II
- Snake game in PyGTK
- Custom widget in PyGTK
- PHP GTK tutorial
- C# Qyoto tutorial
- Ruby Qt tutorial
- Visual Basic Qyoto tutorial
- Mono IronPython Winforms tutorial
- Introduction
- First steps in IronPython Mono Winforms
- Layout management
- Menus and toolbars
- Basic Controls in Mono Winforms
- Basic Controls II in Mono Winforms
- Advanced Controls in Mono Winforms
- Dialogs
- Drag & drop in Mono Winforms
- Painting
- Painting II in IronPython Mono Winforms
- Snake in IronPython Mono Winforms
- The Tetris game in IronPython Mono Winforms
- FreeBASIC GTK tutorial
- Jython Swing tutorial
- JRuby Swing tutorial
- Visual Basic Winforms tutorial
- JavaScript GTK tutorial
- Ruby HTTPClient tutorial
- Ruby Faraday tutorial
- Ruby Net::HTTP tutorial
- Java 2D games tutorial
- Java 2D tutorial
- Cairo graphics tutorial
- PyCairo tutorial
- HTML5 canvas tutorial
- Python tutorial
- Python language
- Interactive Python
- Python lexical structure
- Python data types
- Strings in Python
- Python lists
- Python dictionaries
- Python operators
- Keywords in Python
- Functions in Python
- Files in Python
- Object-oriented programming in Python
- Modules
- Packages in Python
- Exceptions in Python
- Iterators and Generators
- Introspection in Python
- Ruby tutorial
- PHP tutorial
- Visual Basic tutorial
- Visual Basic
- Visual Basic lexical structure
- Basics
- Visual Basic data types
- Strings in Visual Basic
- Operators
- Flow control
- Visual Basic arrays
- Procedures & functions in Visual Basic
- Organizing code in Visual Basic
- Object-oriented programming
- Object-oriented programming II in Visual Basic
- Collections in Visual Basic
- Input & output
- Tcl tutorial
- C# tutorial
- Java tutorial
- AWK tutorial
- Jetty tutorial
- Tomcat Derby tutorial
- Jtwig tutorial
- Android tutorial
- Introduction to Android development
- First Android application
- Android Button widgets
- Android Intents
- Layout management in Android
- Android Spinner widget
- SeekBar widget
- Android ProgressBar widget
- Android ListView widget
- Android Pickers
- Android menus
- Dialogs
- Drawing in Android
- Java EE 5 tutorials
- Introduction
- Installing Java
- Installing NetBeans 6
- Java Application Servers
- Resin CGIServlet
- JavaServer Pages, (JSPs)
- Implicit objects in JSPs
- Shopping cart
- JSP & MySQL Database
- Java Servlets
- Sending email in a Servlet
- Creating a captcha in a Servlet
- DataSource & DriverManager
- Java Beans
- Custom JSP tags
- Object relational mapping with iBATIS
- Jsoup tutorial
- MySQL tutorial
- MySQL quick tutorial
- MySQL storage engines
- MySQL data types
- Creating, altering and dropping tables in MySQL
- MySQL expressions
- Inserting, updating, and deleting data in MySQL
- The SELECT statement in MySQL
- MySQL subqueries
- MySQL constraints
- Exporting and importing data in MySQL
- Joining tables in MySQL
- MySQL functions
- Views in MySQL
- Transactions in MySQL
- MySQL stored routines
- MySQL Python tutorial
- MySQL Perl tutorial
- MySQL C API programming tutorial
- MySQL Visual Basic tutorial
- MySQL PHP tutorial
- MySQL Java tutorial
- MySQL Ruby tutorial
- MySQL C# tutorial
- SQLite tutorial
- SQLite C tutorial
- SQLite PHP tutorial
- SQLite Python tutorial
- SQLite Perl tutorial
- SQLite Ruby tutorial
- SQLite C# tutorial
- SQLite Visual Basic tutorial
- PostgreSQL C tutorial
- PostgreSQL Python tutorial
- PostgreSQL Ruby tutorial
- PostgreSQL PHP tutorial
- PostgreSQL Java tutorial
- Apache Derby tutorial
- SQLAlchemy tutorial
- MongoDB PHP tutorial
- MongoDB Java tutorial
- MongoDB JavaScript tutorial
- MongoDB Ruby tutorial
- Spring JdbcTemplate tutorial
- JDBI tutorial
First steps in UI
In this part of the Windows API tutorial, we will create some simple UI examples.
Simple program
Here is a very simple program. It will pop up a small dialog box.
simple.c
#include <windows.h> int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int CmdShow) { MessageBoxW(NULL, L"First Program", L"First", MB_OK); return 0; }
A small dialog box is shown on the screen. It has a caption, a message, and an OK button.
#include <windows.h>
We include the basic function declarations, constants, data types, and structures.
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int CmdShow)
The wWinMain()
function is an entry point to our application.
MessageBoxW(NULL, L"First Program", L"First", MB_OK);
The MessageBoxW()
function displays a simple message box. The first parameter is the owner window. In our case, the dialog box has no owner. The next two parameters provide the message text and the caption. The last parameter defines the message dialog type. The MB_OK
value causes the dialog to have one OK button.

Centering a window
In the next code example, we will center the window on the screen. The SetWindowPos()
function changes the size, position, and Z order of a child, a pop-up, or a top-level window.
BOOL WINAPI SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags);
The first parameter is a handle to the window. The second parameter is a handle to the window to precede the positioned window in the Z order or a special flag; for instance, the HWND_BOTTOM
flag places the window at the bottom of the Z order and the HWND_TOP
flag at the top of the Z order. The x
and y
parameters are the new positions of the left and top sides of the window, in client coordinates. The cx
and cy
are the new width and height dimensions of the window, in pixels. The last parameter is a combination of sizing and positioning flags; for instance SWP_NOMOVE
retains the current position (ignores x
and y
parameters) or SWP_NOSIZE
retains the current size (ignores cx
and cy
parameters).
centering.c
#include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void CenterWindow(HWND); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.lpszClassName = L"Center"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Center", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 150, 0, 0, hInstance, 0); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: CenterWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProcW(hwnd, msg, wParam, lParam); } void CenterWindow(HWND hwnd) { RECT rc = {0}; GetWindowRect(hwnd, &rc); int win_w = rc.right - rc.left; int win_h = rc.bottom - rc.top; int screen_w = GetSystemMetrics(SM_CXSCREEN); int screen_h = GetSystemMetrics(SM_CYSCREEN); SetWindowPos(hwnd, HWND_TOP, (screen_w - win_w)/2, (screen_h - win_h)/2, 0, 0, SWP_NOSIZE); }
In order to center a window on the screen, we need to have the dimensions of the window and of the screen.
case WM_CREATE: CenterWindow(hwnd); break;
We call the user defined CenterWindow()
function during the WM_CREATE
message.
GetWindowRect(hwnd, &rc) ;
With the GetWindowRect()
function, we retrieve the dimensions of the bounding rectangle of the specified window.
int win_w = rc.right - rc.left; int win_h = rc.bottom - rc.top;
The window width and height are computed.
int screen_w = GetSystemMetrics(SM_CXSCREEN) int screen_h = GetSystemMetrics(SM_CYSCREEN);
With the GetSystemMetrics()
function, we determine the screen width and height.
SetWindowPos(hwnd, HWND_TOP, (screen_w - win_w)/2, (screen_h - win_h)/2, 0, 0, SWP_NOSIZE);
We use the SetWindowPos()
function to position the application window in the center of the screen.
Hot key
In the following example we show how to register a hot key. A hot key is a key combination for executing a specific action. A hot key is registered with the RegisterHotKey()
function.
BOOL WINAPI RegisterHotKey(HWND hWnd, int id, UINT fsModifiers, UINT vk);
The first parameter is a handle to the window that will receive the WM_HOTKEY
message generated by the hot key. The second parameter is the ID of the hot key. The third parameter consists of modifiers; keys that must be pressed in combination with the key specified by the vk
parameter in order to generate the WM_HOTKEY
message. Examples of modifiers include MOD_ALT
or MOD_CONTROL
. The last parameter is the virtual key code of the hot key.
hotkey.c
#include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void CenterWindow(HWND); #define ID_HOTKEY 1 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { HWND hwnd; MSG msg; WNDCLASSW wc = {0}; wc.lpszClassName = L"Application"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); hwnd = CreateWindowW(wc.lpszClassName, L"Hot key", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 270, 170, 0, 0, 0, 0); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: RegisterHotKey(hwnd, ID_HOTKEY, MOD_CONTROL, 0x43); break; case WM_HOTKEY: if ((wParam) == ID_HOTKEY) { CenterWindow(hwnd); } break; case WM_DESTROY: UnregisterHotKey(hwnd, ID_HOTKEY); PostQuitMessage(0); break; } return DefWindowProcW(hwnd, msg, wParam, lParam); } void CenterWindow(HWND hwnd) { RECT rc = {0}; GetWindowRect(hwnd, &rc); int win_w = rc.right - rc.left; int win_h = rc.bottom - rc.top; int screen_w = GetSystemMetrics(SM_CXSCREEN); int screen_h = GetSystemMetrics(SM_CYSCREEN); SetWindowPos(hwnd, HWND_TOP, (screen_w - win_w)/2, (screen_h - win_h)/2, 0, 0, SWP_NOSIZE); }
In the example we register a Ctrl + C hot key. It centers the window on the screen.
case WM_CREATE: RegisterHotKey(hwnd, ID_HOTKEY, MOD_CONTROL, 0x43); break;
During the creation of the window, we register the Ctrl + C hot key with the RegisterHotKey()
function.
case WM_HOTKEY: if ((wParam) == ID_HOTKEY) { CenterWindow(hwnd); } break;
A WM_HOTKEY
message is generated when invoking the hot key. We identify our hot key by examining the wParam
parameter and call the CenterWindow()
function.
case WM_DESTROY: UnregisterHotKey(hwnd, ID_HOTKEY); PostQuitMessage(0); break;
When the window is destroyed, we unregister the hot key with the UnregisterHotKey()
function. The MSDN is not clear about whether it is compulsory to call this function.
More windows
A window is created from a specific window class. A window class defines a set of behaviours that several windows have in common. Some classes are already predefined in the system. A custom window class must be registered. After that, we can create windows of this new window class. A window is created using the CreateWindowW()
function. Its first parameter is the window class name.
Each window has a window procedure. It is a function that is called by the OS when users interact with the window. In the following example, we create three windows: one parent window and two child windows.
morewindows.c
#include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK PanelProc(HWND, UINT, WPARAM, LPARAM); void RegisterRedPanelClass(void); void RegisterBluePanelClass(void); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.lpszClassName = L"Windows"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Windows", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 180, 0, 0, hInstance, 0); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: RegisterRedPanelClass(); CreateWindowW(L"RedPanelClass", NULL, WS_CHILD | WS_VISIBLE, 20, 20, 80, 80, hwnd, (HMENU) 1, NULL, NULL); RegisterBluePanelClass(); CreateWindowW(L"BluePanelClass", NULL, WS_CHILD | WS_VISIBLE, 120, 20, 80, 80, hwnd, (HMENU) 2, NULL, NULL); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } LRESULT CALLBACK PanelProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_LBUTTONUP: MessageBeep(MB_OK); break; } return DefWindowProcW(hwnd, msg, wParam, lParam); } void RegisterRedPanelClass(void) { HBRUSH hbrush = CreateSolidBrush(RGB(255, 0, 0)); WNDCLASSW rwc = {0}; rwc.lpszClassName = L"RedPanelClass"; rwc.hbrBackground = hbrush; rwc.lpfnWndProc = PanelProc; rwc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&rwc); } void RegisterBluePanelClass(void) { HBRUSH hbrush = CreateSolidBrush(RGB(0, 0, 255)); WNDCLASSW rwc = {0}; rwc.lpszClassName = L"BluePanelClass"; rwc.hbrBackground = hbrush; rwc.lpfnWndProc = PanelProc; rwc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&rwc); }
We have an application window with two child windows. The two child windows have blue and red backgrounds.
HBRUSH hbrush = CreateSolidBrush(RGB(255, 0, 0)); ... rwc.hbrBackground = hbrush;
To create a coloured window background, we create a custom solid brush by calling the CreateSolidBrush()
function. To specify a colour, we use the RGB
macro. As we know, any colour can be created by combining red, green, and blue colours. Then we set the hbrBackground
parameter of the window class structure to this newly created brush.
RegisterRedPanelClass(); CreateWindowW(L"RedPanelClass", NULL, WS_CHILD | WS_VISIBLE, 20, 20, 80, 80, hwnd, (HMENU) 1, NULL, NULL);
First we register a new window class. After this step, we create a window of this class.
Both of our child windows share the PanelProc
window procedure. This procedure is called by the Windows OS when we interact with it.
case WM_LBUTTONUP: MessageBeep(MB_OK); break;
We interact with our child windows, when we click on them. By left clicking on the child window, the Windows OS calls the child window procedure and sends a WM_LBUTTONUP
message. In our example, we call the MessageBeep()
function. If we left click on the background of the two child windows, we hear the Windows default beep sound.
void RegisterBluePanelClass(void) { HBRUSH hbrush = CreateSolidBrush(RGB(0, 0, 255)); WNDCLASSW rwc = {0}; rwc.lpszClassName = L"BluePanelClass"; rwc.hbrBackground = hbrush; rwc.lpfnWndProc = PanelProc; rwc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&rwc); }
This function registers a new window class. Windows of this window class type have red backgrounds. The edit, button, and static controls are created from predefined window classes, which are already available to all processes. So in these cases we do not need to register a window class for them.

The escape key
Applications are often terminated by pressing the Escape key. A message box is also shown to confirm the termination.
escapekey.c
#include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int CmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.lpszClassName = L"Escape"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Escape", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 180, 0, 0, hInstance, 0); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_KEYDOWN: if (wParam == VK_ESCAPE) { int ret = MessageBoxW(hwnd, L"Are you sure to quit?", L"Message", MB_OKCANCEL); if (ret == IDOK) { SendMessage(hwnd, WM_CLOSE, 0, 0); } } break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProcW(hwnd, msg, wParam, lParam); }
It is a common practice to ask a user if he really wants to close an application. If we have a clock or a calculator then it does not matter that much. But if we have a text editor or a drawing application, it does matter. We might accidentally press the Escape key and loose all our modifications.
case WM_KEYDOWN: if (wParam == VK_ESCAPE) { int ret = MessageBoxW(hwnd, L"Are you sure to quit?", L"Message", MB_OKCANCEL); if (ret == IDOK) { SendMessage(hwnd, WM_CLOSE, 0, 0); } } break;
If we press a key, the window procedure receives a WM_KEYDOWN
message. The wParam
parameter has a key code. We can close the window by sending a WM_CLOSE
message. The message is sent with the SendMessage()
function.
Moving a window
When we move a window on the screen, the window procedure receives the WM_MOVE
message. In our example we display the current window position on the screen—we display the coordinates of the top-left corner of the window.
moving.c
#include <windows.h> #include <wchar.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void CreateLabels(HWND); HWND hwndSta1; HWND hwndSta2; int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int CmdShow) { HWND hwnd; MSG msg; WNDCLASSW wc = {0}; wc.lpszClassName = L"Moving"; wc.hInstance = hInstance ; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); hwnd = CreateWindowW(wc.lpszClassName, L"Moving", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 150, 150, 250, 180, 0, 0, hInstance, 0); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { wchar_t buf[10]; RECT rect; switch(msg) { case WM_CREATE: CreateLabels(hwnd); break; case WM_MOVE: GetWindowRect(hwnd, &rect); StringCbPrintfW(buf, BUF_LEN, L"%ld", rect.left); SetWindowTextW(hwndSta1, buf); StringCbPrintfW(buf, BUF_LEN, L"%ld", rect.top); SetWindowTextW(hwndSta2, buf); break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProcW(hwnd, msg, wParam, lParam); } void CreateLabels(HWND hwnd) { CreateWindowW(L"static", L"x: ", WS_CHILD | WS_VISIBLE, 10, 10, 25, 25, hwnd, (HMENU) 1, NULL, NULL); hwndSta1 = CreateWindowW(L"static", L"150", WS_CHILD | WS_VISIBLE, 40, 10, 55, 25, hwnd, (HMENU) 2, NULL, NULL); CreateWindowW(L"static", L"y: ", WS_CHILD | WS_VISIBLE, 10, 30, 25, 25, hwnd, (HMENU) 3, NULL, NULL); hwndSta2 = CreateWindowW(L"static", L"150", WS_CHILD | WS_VISIBLE, 40, 30, 55, 25, hwnd, (HMENU) 4, NULL, NULL); }
The creation of the static text controls is delegated to the CreateLabels()
function.
void CreateLabels(HWND hwnd) { CreateWindowW(L"static", L"x: ", WS_CHILD | WS_VISIBLE, 10, 10, 25, 25, hwnd, (HMENU) 1, NULL, NULL); hwndSta1 = CreateWindowW(L"static", L"150", WS_CHILD | WS_VISIBLE, 40, 10, 55, 25, hwnd, (HMENU) 2, NULL, NULL); CreateWindowW(L"static", L"y: ", WS_CHILD | WS_VISIBLE, 10, 30, 25, 25, hwnd, (HMENU) 3, NULL, NULL); hwndSta2 = CreateWindowW(L"static", L"150", WS_CHILD | WS_VISIBLE, 40, 30, 55, 25, hwnd, (HMENU) 4, NULL, NULL); }
There are four static text controls. Two of them change during the lifetime of the application. So we need only two handles.
case WM_MOVE: GetWindowRect(hwnd, &rect); StringCbPrintfW(buf, BUF_LEN, L"%ld", rect.left); SetWindowTextW(hwndSta1, buf); StringCbPrintfW(buf, BUF_LEN, L"%ld", rect.top); SetWindowTextW(hwndSta2, buf); break;
To get the window coordinates, we call the GetWindowRect()
function. Since a coordinate is a number, we must convert it to a string. To accomplish this, we use the StringCbPrintfW()
function.

Flashing a window
Sometimes when an important event happens, the title bar or the taskbar button start to flash. The flashing is the change of the title bar from inactive status to active status and vice versa. This is a common feature in Miranda IM when we receive a new message.
flashing.c
#include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.lpszClassName = L"Flash"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0,IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Flash", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 180, 0, 0, hInstance, 0); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { FLASHWINFO fwi; switch(msg) { case WM_CREATE: CreateWindowW(L"Button", L"Flash", WS_CHILD | WS_VISIBLE, 10, 10, 80, 25, hwnd, (HMENU) 1, NULL, NULL); break; case WM_COMMAND: fwi.cbSize = sizeof(fwi); fwi.dwFlags = FLASHW_ALL; fwi.dwTimeout = 0; fwi.hwnd = hwnd; fwi.uCount = 4; FlashWindowEx(&fwi); break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProcW(hwnd, msg, wParam, lParam); }
In order to flash a window, we must do two steps: create and fill a FLASHWINFO
structure and call the FlashWindowEx()
function.
fwi.dwFlags = FLASHW_ALL;
We have set the FLASHW_ALL
flag. This will flash both the title bar and the taskbar button. To flash only the titlebar, we can use the FLASHW_CAPTION
tag. To flash the taskbar button, we can use the FLASHW_TRAY
flag.
fwi.dwTimeout = 0;
The dwTimeout
member is the rate at which the window is to be flashed, in milliseconds. If dwTimeout
is zero, the function uses the default cursor blink rate.
fwi.hwnd = hwnd; fwi.uCount = 4;
Here we set which window to flash and how many times we want to flash it. In our case, we flash the main window four times.
FlashWindowEx(&fwi);
The FlashWindowEx()
starts the flashing.
In this part of the Windows API tutorial, we have created some simple UI examples.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论