Академический Документы
Профессиональный Документы
Культура Документы
Windows
. capuu
re
. Cepue.o
erop
32.973.2-018.2
004.451
.
95
Win32 API.
592 .: .
Windows. -
.: ,
2008. -
ISBN 978-5-388-00301-0
mre : IWeI : I
/++
Windows
se
Win32.APl
:, 8CIplO ,
++, OIIlolll aonc roe: I Wdows.
lIpaIcrxa , ' orpac apaary
are , FC I Wdows
Win32
.! JIJDIercJI [ ero
II.
000
2008
.
.
, , , 8eJlbCJO
. , ,
, .
ISBN 978-5-388-00301-0
73, . 29.
005-93, 2; 95 3005 - rrepa U[.
28.05.08. 7lOl16. Ycn. . . 47,73. paz2500.
Omea JI CtP IIea'l1 . . .
197110, Cahrr-IIeep, :nn:& ., 15.
000 Ihrrep
IUI -
198206, Cabrr-IIeep,
cme , .
CI yI
............................................................................... 13
1. Hello, World!,
Windows ......... 16
2. GDI
. , , ......... 58
3. GDI. , , ....................... 159
4. ........................................................ 213
5. Windows- ............................. 242
6. ..................................... 272
7. .................................................... 304
8. ....... 379
9. .................................................... 441
10. ..................................................... 485
11. DLL ........ 515
12. ..................................... 539
1. Visual C++ 6.0 ....... 563
2. Visual Studio.NET .. 577
3. Spy++ ............................. 584
............................................................................... 587
........................................................... 588
............................................................................... 13
........................................................................ 14
............................................................................... 14
........................................................................................ 15
1. Hello, World!,
Windows ........... 16
................................................................................... 16
................................................. 16
.................................................................................. 17
............................................................................ 18
................................................. 19
DLL ......................................................................... 19
- ................................... 20
Win32 .............................................................................. 20
, .................................................. 21
.............................................................................. 22
................................................................................... 23
.................................................................. 25
Windows ................................................... 25
Hello, world! ........................................... 30
....................................................... 31
...................................................................... 32
...................................................................................... 35
CreateWindowEx ............................................. 38
............................................................... 39
.......................................................................... 40
.............................................................................. 42
2. GDI .
, , .......................................... 58
.................................................................................. 59
................................................................. 59
Windows. ............................................................... 60
................................................................................. 60
WM_PAINT .................................................. 63
................................................................................ 65
( ) .......................................... 65
....................................................................... 66
.................................................................. 66
...................................................... 66
, ...................................... 66
.................................................................. 67
............................................................ 68
............................................................. 68
....................... 69
................................................................. 72
................................. 74
. .......................................................... 76
HLS .................................................................. 76
RGB ................................................................. 76
.......................................... 77
.................................................................................... 78
, ......................... 78
. ............................... 79
............ 81
............................................ 81
........................................................................................ 82
.............................................................................. 83
..................................................................................................... 84
....................................................................................... 86
........................................................................................................ 87
............................................................................... 88
...................................................................................... 89
.............................................................................. 93
......................................................................................................... 96
............................................................................... 97
....................................................................... 97
.................................................................................... 101
................................................................................... 101
, , ............. 105
.................................................................................... 107
................................................................................. 109
............................................................................... 109
.......................................................... 111
........................................................................... 111
............................................................................................ 112
.................................................................................. 113
............................................................. 114
Unicode ................................................................................................. 117
............................................................................................... 118
........................................................................................ 129
........................................................ 141
.................................................................................... 146
.......................................................... 146
................................................... 153
............................................................................... 161
.............................................................................. 166
....................................................................................................... 174
- ........................................................... 175
- ............................................................... 193
DIB- ........................................................................................... 200
........................................................... 202
............................................................................................... 206
............................................................................ 207
................................................................ 210
4. .......................................................... 213
................................................................................................ 213
.......................................................................................... 214
.............................................................................. 215
........................................................................ 215
........................................................................ 217
................................................................................ 219
....................................................... 220
........................................................................................................ 225
, ...................................................... 226
................................................................................. 226
................................................................. 227
................................................ 227
...................................................................................... 228
................................................................ 234
................. 237
................................................................... 263
........................................................... 264
.......................................................................................... 268
6. ....................................... 272
........................................................................ 272
.............................................................................. 273
................................................................................... 274
............................................................ 273
............................................................................ 275
......................................................................... 275
, ............................................ 276
........................................................... 276
....................................................................................... 276
......................................................................... 277
......................................................................... 278
........................................................................................ 279
i- .......................... 279
................................... 280
....................................................... 280
..................................................................... 281
CheckMenuItem ....................................................................... 282
CheckMenuRadioItem .............................................................. 282
EnableMenuItem ...................................................................... 283
ModifyMenu ............................................................................. 283
.......................................... 284
....................................................................................... 284
MenuDemo1 ........................................................................... 286
...................................................................... 293
........................................... 293
...................................................................................... 293
.......................................................................................... 293
MenuDemo2 ...................................................................... 294
...................................................................................... 299
............................................ 299
..................................................................... 300
....................................................... 301
.......................................... 301
MenuDemo3 ...................................................................... 302
7. ....................................................... 304
.............................................................................. 304
................................................. 305
................................................... 307
.................................................................... 307
.................................................................. 308
.................................................................................... 308
............................ 309
.......................................... 311
........................................ 312
..................... 314
......................... 316
......................................... 320
........................................... 323
.................................................................................................. 323
Owner draw ............................................................................... 325
................................................................................................. 331
.................................................................................... 333
.................................................................................. 333
, .. 334
.... 340
........................................................................... 341
.................................................................................................. 344
..................................................................... 356
................................................................................. 366
........... 366
............................. 367
........................................................................................ 372
...................................................... 374
8. .......... 379
.................................................................................. 380
.................................................................. 380
......................... 382
.............................. 383
10
............................................................................. 384
........................................................ 385
........................................................................... 385
.................................................................................... 406
KWnd KWndEx ................................................. 408
................................................................................. 413
.................................................................... 423
............................................................................. 423
............................................................................................. 428
................................................................ 435
............................................................................... 435
9. ....................................................... 441
............................................................................................ 441
.................................................................................... 443
.............................................................................. 444
.......................... 445
............................................................................ 447
CreateProcess ................................................. 447
........................................................................... 448
........................................... 449
................................................................................ 451
CreateThread ........................................................................... 451
Sleep ...................................................................................... 452
................................................... 452
..................... 456
.......................................................................................... 459
Interlocked- ............................ 459
............................................................................. 460
Wait- ........................................................................................ 461
................................................................................................ 464
............................................................................................. 466
............................................................................................. 467
........................................................... 469
. ........................ 470
, ............................................... 472
.. 472
11
- ...................................................................... 473
WM_COPYDATA ....................... 474
ServerApp ......................................................................... 475
ClientApp .......................................................................... 479
.......................................................... 483
? ................................................ 484
12
API Application Programming Interface (
). API
, (),
.
Win32 API ,
Microsoft Windows 98, Windows NT Windows 2000.
32, .
Windows
,
MSDN,
. , ,
, .
,
.
Windows C/C++ Win32 API.
.
, Windows
. ,
, , .
DLL. : ,
. C/C++
Windows.
, , MFC (Microsoft Foundation
Classes) Windows Forms.
, MFC, Windows Forms,
Windows API.
Win32 API
Windows. , ,
MFC Windows Forms,
,
14
. , , Win32
API,
.
,
. , MFC Windows Forms
,
.
(,
),
Win32 API.
:
, Windows
(Charles Petzold) [1], (Jeffrey
Richter) [5] (Feng Juan) [6];
;
Windows
, .
, ,
Win32 API. ,
2006 . ,
DLL.
.
, , ,
, C++,
Windows.
, C/C++ ,
, .
, ,
.
:)
C/C++ Win32 API. ,
.
Win32 API,
.
Microsoft Windows 2000 Professional Microsoft Visual Studio
6.0. Windows 98, Windows NT/2000
15
,
comp@piter.com ( , ).
!
, , http://
www.piter.com/download.
: http://www.piter.com.
16
Hello, World!,
Windows
, ,
Windows. , ,
Microsoft Word
Microsoft Office. ,
, Windows. ,
,
Windows.
Windows
MSDOS ,
. :
;
Graphical User Interface1 (GUI)
.
,
.
, ,
.
.
1
17
, ,
, ,
.
Windows , .
,
. ,
,
Windows,
.
. , Visual Studio 6.0
, ,
,
Windows Media. explorer.exe
.
Windows
( ) ,
,
. ,
. Windows 95 .
,
, .
Windows .
Windows (process).
,
.
() (thread),
, .
,
.
,
.
.
? ,
.
, . ,
COM,
.
18
, , ,
. (top
level window)1, (child windows).
(parent windows). 1.1
.
. 1.1. ,
,
.
,
. , . ,
, ,
.
.
,
, .
, , .
,
.
Windows
. ,
,
. ,
1
19
,
,
. , Windows,
,
DLL (dynamic link libraries). Windows
DLL.
Windows, ,
.
Windows. Win32 API 32
.
Windows
. , Windows,
, , ,
.
Win32 API, (Graphics De
vice Interface, GDI).
GDI
.
(, LineTo )
. ,
Win32 API, .
, , Win32 API,
,
Windows.
, . . Windows
,
, SDK (Software Development
Kit ) / DDK (Driver Development Kit
).
,
.
DLL
Win32 API ,
. Windows
. windows.h.
.
Win32 API
C/C++. ,
C/C++
( ),
Windows
20
( ).
(DLL) .dll.
SYSTEM
Windows.
, .
, . ,
,
Win32 API.
-
Windows
, ,
. ,
, , ,
.
,
.
.
,
, ,
.
,
.
.
Windows.
Windows, ,
, , ,
, , , .
, Windows
, .
handle1. .
. Windows
.
Win32
, C/C++,
Windows .
#define #typedef Win32.
. 1.1
Windows.
1
21
1.1. Win32
BOOL
( bool)
BYTE
(8- )
DWORD
32-
HANDLE
HBITMAP
( )
HBRUSH
HCURSOR
HDC
HFONT
HICON
()
HINSTANCE
HMENU
HPEN
HWND
INT
32-
LONG
32-
LPARAM
, lParam,
LPCSTR
C-1
LPCTSTR
LPCWSTR
Unicode-2
LPSTR
C-
LPTSTR
LPWSTR
Unicode-
LRESULT
LONG,
NULL
((void*) 0)
TCHAR
UINT
32-
WPARAM
, wParam,
,
.
, ,
, ,
1
C .
ANSI. , ,
C.
Unicodec ,
. UNICODE,
, 2.
22
.
, ,
. ,
, .
, :
, ;
() ;
, .
, Windows .
, ,
,
. Windows
?
, .
, , ,
. Windows , ,
,
.
, ,
. , ,
,
.
, Windows
, .
.
, ,
, :
, .
,
, ,
.
,
, , Windows.
, , .
. ,
.
.
CALLBACK.
:
LRESULT CALLBACK _(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
23
LRESULT (. . 1.1),
hWnd , , uMsg ,
wParam lParam .
, WndProc.
switch,
.
Windows
.
#define winuser.h.
.
(window messages),
WM_, : WM_PAINT, WM_SIZE, WM_MOVE
. ,
: BM_ ,
EM_ , LB_ .
.
, , .
.
.
.
.
(window class), ,
.
, , ,
. , ,
,
.
CreateWindow,
.
, ,
. , Windows
BUTTON. ,
,
.
, , , .
.
Windows
, .
,
.
24
Windows C++ , ,
MFC. ,
Windows - .
, ?
.
Windows
. WinMain.
,
.
? , ,
, Windows
. GetMessage.
WM_QUIT, ,
.
WM_QUIT,
DispatchMessage, Windows.
Windows
, Windows .
Windows ,
DispatchMessage, .
, , , ...
Windows
Microsoft Visual C++ 6.0, , ,
1, ,
, ,
.
OK! ?.. .
Win32 Application HelloFromMsgBox.
HelloFromMsgBox.cpp
:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, "Hello, Win32 world!", "Hello from Message Box", MB_OK);
return 0;
}
Windows
25
. ,
.
, . ,
. 1.2.
. 1.2. HelloFromMsgBox
?
Hello, Win32 world!. . ,
. . OK. .
.
, .
, ?..
,
WinMain?
.
:
#include <windows.h>
Windows
.
WinMain:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
LPSTR lpCmdLine ,
, .
, Norton Commander.
, ,
.
EXE. (
EXE),
.
, Object.
Windows 3.x,
.
26
int nCmdShow ,
ShowWindow. .
WINAPI ,
Win32 .
, ,
WinMain .
, .
MessageBox, , ,
.
?
?.. :
MessageBox.
,
MessageBox, MSDN1.
F1.
MessageBox .
MessageBox, , ,
. ,
.
2:
:
hWnd . NULL,
.
lpText , .
lpCaption ,
.
uType ,
, .
MessageBox
7. ,
,
.
, Windows. ,
MessageBox,
, .
( ) ,
.
Windows
27
,
, Windows.
, ,
.
, , ! , ,
WinMain . .
MessageBox. .
Windows, ,
,
Microsoft (Charles Simonyi).
, ,
. .
, ,
, . ,
nMyVariable .
. 1.2.
1.2.
b
by
c
dw
fn
h
i
l
lp
lpsz
n
p
pfn
psz
pv
sz
u
v
w
x
BOOL
BYTE
har
DWORD
INT
LONG
,
short int
,
void
,
UINT
void
WORD
, x
, y
, , ,
, lpText uType. ,
,
. ,
, ,
.
28
Windows,
, Win32
:
(screen coordinates);
(window coordinates);
(client coordinates).
. 1.3 ,
.
. 1.3. Windows
, .
,
.
.
.
, Move (),
Size (), Minimize (), Maximize (), Close ().
,
.
,
, .
29
Hello, World!
.
.
.
, Windows
. .
Hello, World!
Win32
:
WinMain ,
;
WndProc ,
.
Windows
:
WinMain ( )
{
;
;
{
;
Windows ;
}
;
}
WndProc ( )
{
;
;
}
, ,
Hello, World!. ,
1.1, Hello1.cpp.
1.1. Hello1
//////////////////////////////////////////////////////////////////////
// Hello1.cpp
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
HWND hMainWnd;
char szClassName[] = "MyClass";
30
1.1 ()
MSG msg;
WNDCLASSEX wc;
//
wc.cbSize
= sizeof(wc);
wc.style
= CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc
= WndProc;
wc.cbClsExtra
= 0;
wc.cbWndExtra
= 0;
wc.hInstance
= hInstance;
wc.hIcon
= LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor
= LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.hIconSm
= LoadIcon(NULL, IDI_APPLICATION);
//
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, "Cannot register class", "Error", MB_OK);
return 0;
}
//
hMainWnd = CreateWindow(
szClassName, "A Hello1 Application", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
(HWND)NULL, (HMENU)NULL,
(HINSTANCE)hInstance, NULL
);
if (!hMainWnd) {
MessageBox(NULL, "Cannot create main window", "Error", MB_OK);
return 0;
}
//
ShowWindow(hMainWnd, nCmdShow);
// UpdateWindow(hMainWnd); // . " "
//
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
switch (uMsg)
Hello, World!
31
{
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rect);
DrawText(hDC, "Hello, World!", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER );
EndPaint(hWnd, &ps);
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
Hello1, .
,
. 1.4.
. 1.4. Hello1
. Hello1
, .
Hello1.cpp : WinMain WndProc. WinMain
. WndProc
32
. ,
, ,
.
Hello1.cpp WndProc
Windows. WinMain
WndProc ( wc.lpfnWndProc),
WndProc ,
WinMain.
,
. Windows.
,
, CS_HREDRAW, IDI_APPLICATION, IDC_ARROW,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT. .
, .
. 1.3.
1.3.
CS_
CW_
DT_
IDC_
IDI_
()
WM_
WS_
,
Windows. . 1.1.
WinMain
. WNDCLASSEX,
RegisterClassEx.
WNDCLASSEX :
typedef struct tagWNDCLASSEX {
UINT cbSize;
//
UINT style;
//
WNDPROC lpfnWndProc;
// ( )
int cbClsExtra;
// ,
//
int cbWndExtra;
// ,
//
HINSTANCE hInstance;
// ,
//
HICON hIcon;
//
HCURSOR hCursor;
//
HBRUSH hbrBackground; // ,
//
Hello, World!
33
LPCTSTR lpszMenuName;
// , ,
//
LPCTSTR lpszClassName; // ,
HICON hIconSm;
//
} WNDCLASSEX;
,
.
LP lp (long pointer), 16- Windows, 16- 32-
. Win 32 API 32 .
lpfn (long pointer to a function). cb
(counter of bytes). hbr (handle
to a brush).
WNDCLASSEX.
, cbSize, .
, style,
, . 1.41.
1.4.
CS_GLOBALCLASS
, .
DLL
CS_HREDRAW
CS_NOCLOSE
Close
CS_OWNDC
CS_VREDRAW
Windows ,
CS_, 32 ,
. , CS_VREDRAW
0x0001, CS_HREDRAW 0x0002.
(bit flags).
C++.
CS_HREDRAW | CS_VREDRAW. ,
,
. A Hello1
Application, ,
.
.
, lpfnWndProc, (
WndProc).
1
. . MSDN.
34
46 1.
, hIcon, ,
. (: , )
, Windows
. hIcon LoadIcon,
:
HICON LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName);
, lpIconName,
, hInstance2.
()
, NULL.
,
IDI_ ( ID for icon).
. 1.5.
1.5.
IDI_APPLICATION
IDI_ASTERISK
IDI_ERROR
IDI_EXCLAMATION
IDI_HAND
IDI_INFORMATION
IDI_QUESTION
IDI_WARNING
, IDI_INFORMATION
.
, IDI_WARNING
, IDI_ERROR
i,
?
!,
IDI_WINLOGO
Windows
hCursor ,
. hCursor
LoadCursor, :
HCURSOR LoadCursor(HINSTANCE hInstance, LPCTSTR lpCursorName);
, (lpCursorName), , (hInstance)3.
(
) , NULL.
. 1.6.
1.6.
IDC_APPSTARTING
IDC_ARROW
cbClsExtra cbWndExtra .
5.
5.
Hello, World!
35
IDC_CROSS
IDC_HELP
IDC_IBEAM
IDC_NO
IDC_SIZEALL
IDC_SIZENESW
, - -
IDC_SIZENS
IDC_SIZENWSE
, - -
IDC_SIZEWE
IDC_UPARROW
IDC_WAIT
, hbrBackground, ,
. (brush)
,
, . Windows
. GetStockObject
WHITE_BRUSH .
HGDIOBJ, HBRUSH.
, lpszMenuName, , ,
.
, NULL.
lpszClassName , .
lpClassName CreateWindow.
, hIconSm, ,
,
. 16 16 .
NULL, , hIcon,
.
, .
, RegisterClassEx.
1 RegisterClass Windows.
RegisterClass,
WNDCLASS ( WNDCLASSEX).
,
. CreateWindow,
:
HWND CreateWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
1
//
//
//
//
Ex, extended .
36
//
//
//
//
//
//
//
// ,
//WM_CREATE
);
, , Create
Window ,
, ,
Windows.
, lpClassName, ,
. ,
RegisterClassEx RegisterClass,
, . 1.7.
1.7.
BUTTON
, , ,
, LISTBOX
EDIT.
LISTBOX
( ),
,
.
, MDI-
Rich Edit 1.0.
EDIT
Rich Edit 2.0 3.01.
RICHEDIT
.
BS_
COMBOBOX
EDIT
LISTBOX
MDICLIENT
RICHEDIT
RICHEDIT_CLASS
SCROLLBAR
STATIC
CBS_
ES_
LBS_
ES_
ES_
SBS_
SS_
, lpWindowName, ,
. . ,
(. . 1.3),
BUTTON .
1
Windows, .
Hello, World!
37
, dwStyle, ,
, . 1.8.
.
,
. ,
. 1.71.
1.8.
WS_BORDER
WS_CAPTION
WS_THICKFRAME
WS_VISIBLE
, (
WS_BORDER)
.
WS_POPUP
,
, , .
( )
,
,
.
WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU,
WS_THICKFRAME, WS_MINIMIZEBOX WS_MAXIMIZEBOX
.
WS_CHILD
WS_BORDER, WS_POPUP WS_SYSMENU.
,
WS_CAPTION
, ,
TAB
,
,
WS_VSCROLL
WS_CHILD
WS_CLIPCHILDREN
WS_CLIPSIBLINGS
WS_DLGFRAME
WS_GROUP
WS_HSCROLL
WS_MAXIMIZE
WS_MAXIMIZEBOX
WS_MINIMIZE
WS_MINIMIZEBOX
WS_OVERLAPPED
WS_OVERLAPPEDWINDOW
WS_POPUP
WS_POPUPWINDOW
WS_SYSMENU
WS_TABSTOP
WS_OVERLAPPEDWINDOW.
, , ,
1
.
MSDN.
38
,
, .
, x,
. x y ,
.
x , CW_USEDEFAULT.
Windows x y . ,
,
.
, y, .
x CW_USEDEFAULT, y .
, nWidth, .
CW_USEDEFAULT, nWidth nHight
.
, nHight, . nWidth
CW_USEDEFAULT, nHight .
, hWndParent,
NULL, .
, ,
, .
, hMenu,
. .
, ( lpszMenuName WNDCLASSEX), hMenu NULL.
, hMenu
,
. , ,
WM_COMMAND, .
, hInstance,
, WinMain.
, lParam,
NULL.
,
WM_CREATE.
, CreateWindow . ,
. ,
NULL.
,
MessageBox.
CreateWindowEx
CreateWindow
CreateWindowEx, :
HWND CreateWindowEx(DWORD dwExStyle, LPCTSTR lpClassName,
LPCTSTR lpWindowName, DWORD dwStyle,
int x, int y, int nWidth,
Hello, World!
39
, , ,
CreateWindow. , dwExStyle, ,
, dwStyle.
, ,
. 1.9.
MSDN.
1.9.
WS_EX_ACCEPTFILES
WS_EX_CLIENTEDGE
WS_EX_CONTROLPARENT
Tab
WS_EX_MDICHILD
WS_EX_STATICEDGE
.
,
WS_EX_TOOLWINDOW
WS_EX_TRANSPARENT
. ,
, WM_PAINT
,
WS_EX_WINDOWEDGE
CreateWindowEx , CreateWindow,
,
Windows.
1.
ShowWindow,
:
BOOL ShowWindow(HWND hWnd, int nCmdShow);
,
, .
,
nCmdShow WinMain.
,
. 1.102.
1
7,
8.
. . MSDN.
40
SW_HIDE
SW_MAXIMIZE
SW_MINIMIZE
SW_SHOW
SW_SHOWMINNOACTIVE
, Win32 API,
MSDN ShowWindow UpdateWindow, WM_PAINT,
. , . , ShowWindow
WM_SIZE WM_MOVE, WM_SIZE, WM_PAINT. UpdateWindow .
.
. Windows (message queue)
, .
Windows ,
.
, ,
(message loop):
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
msg MSG,
Windows :
typedef struct tagMSG
HWND
hwnd;
UINT
message;
WPARAM wParam;
LPARAM lParam;
DWORD
time;
POINT
pt;
{
// ,
// ()
// wParam
// lParam
//
// ( )
//
} MSG;
wParam lParam .
POINT :
Hello, World!
41
GetMessage, :
BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
lpMsg MSG,
.
hWnd , .
NULL,
.
wMsgFilterMin
. .
wMsgFilterMax
.
, .
GetMessage TRUE
, WM_QUIT. WM_QUIT,
FALSE.
, ,
msg.wParam.
?
:
TranslateMessage DispatchMessage.
, TranslateMessage ,
. ,
Windows
.
, : WM_KEYDOWN
, WM_KEYUP
. WM_KEYDOWN
1 .
TranslateMessage , WM_KEYDOWN WM_KEYUP,
WM_CHAR, (wParam)
TCHAR2. WM_CHAR ,
GetMessage .
, DispatchMessage msg Windows.
Windows. Windows
,
.
, .
42
,
, . WndProc
( ),
,
, Windows ( DLL).
Windows
, DispatchMessage, while,
.
,
, WM_QUIT.
.
(window
procedure). ,
, , .
:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
MSG. ,
. .
Win32 0 1024.
,
.
WndProc ,
lpfnWndProc wc.
MyClass.
hMainWnd CreateWindow.
hWnd hMainWnd.
(, , ),
hWnd ,
.
switch ,
.
, . ,
,
DefWindowProc. ,
DefWindowProc.
, ,
. Hello1
: WM_PAINT, WM_CLOSE WM_DESTROY.
WM_PAINT
WM_PAINT Win
dows. ,
Hello, World!
43
(invalid) .
WM_PAINT ,
,
Hello1.
?
, ,
. .
,
, CS_HREDRAW |
CS_VREDRAW style . .
Hello1,
, , Windows
. .
, ,
, Windows
. .
, .
, ,
,
WM_PAINT. ,
, ShowWindow.
WM_SIZE WM_MOVE,
WM_SIZE, WM_PAINT.
,
.
WM_PAINT
BeginPaint:
hDC = BeginPaint(hWnd, &ps);
,
, ps PAINTSTRUCT.
, BeginPaint,
1.
.
(device context)
, .
Windows .
,
, ,
, , , .
, hDC
.
,
BeginPaint.
1
PAINTSTRUCT 2.
44
, BeginPaint, Windows
, 1.
, hbrBackground
WNDCLASSEX.
, BeginPaint
(valid), .
WM_PAINT ,
, .
BeginPaint
GetClientRect,
:
GetClientRect(hWnd, &rect);
rect RECT.
RECT, (rectangle),
Windows :
typedef
LONG
LONG
LONG
LONG
} RECT;
struct tagRECT {
left;
top;
right;
bottom;
(left, top)
(right, bottom) .
GetClientRect left top
, right bottom
. ,
rect, DrawText.
Hello, World!
DrawText, :
BOOL DrawText(
HDC hdc,
LPCTSTR lpString,
int nCount,
LPRECT lpRect,
UINT uFormat
);
//
//
//
//
//
2 lpString ,
RECT, ,
uFormat. nCount.
nCount 1, lpString
.
, .
DT_SINGLELINE |
DT_CENTER | DT_VCENTER,
1
ps.
DrawText.
2.
Hello, World!
45
Windows. , ,
,
. Hello, World!
.
(,
), WndProc WM_PAINT.
, GetClientRect
.
WM_PAINT
EndPaint.
,
, . , ,
. ,
, .
SetTextColor
(text color) . SetBkColor
(background color),
, .
(background mix mode), SetBkMode.
OPAQUE1,
,
. TRANSPARENT2,
,
.
,
, . 1.11.
1.11.
OPAQUE
Hello1.
WM_CLOSE WM_DESTROY
WM_CLOSE ,
Alt+F4. ,
: , DefWindowProc
DestroyWindow.
,
1
46
?, .
, WM_DESTROY .
DestroyWindow, ,
. WM_DESTROY.
, WM_DESTROY ,
.
.
WM_DESTROY,
,
. PostQuitMessage,
WM_QUIT.
WM_QUIT, .
: Hello1
Hello, World!.
, ?.. ,
.
Hello, World!
Hello, World! Windows
. ,
: ,
WinMain, Hello1.cpp1,
.
, ,
, C++.
,
? ,
? , .
. KWnd,
, ,
, .
[9],
: .h,
.cpp. ,
, 1.22.
1.2. Hello2
//////////////////////////////////////////////////////////////////////
// KWnd.h
#include <windows.h>
class KWnd {
, 1.
Hello, World!
47
public:
KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
LRESULT (WINAPI *pWndProc)(HWND,UINT,WPARAM,LPARAM),
LPCTSTR menuName = NULL,
int x = CW_USEDEFAULT, int y = 0,
int width = CW_USEDEFAULT, int height = 0,
UINT classStyle = CS_HREDRAW | CS_VREDRAW,
DWORD windowStyle = WS_OVERLAPPEDWINDOW,
HWND hParent = NULL);
HWND GetHWnd() { return hWnd; }
protected:
HWND hWnd;
WNDCLASSEX wc;
};
//////////////////////////////////////////////////////////////////////
// KWnd.cpp
#include "KWnd.h"
KWnd::KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
LRESULT (WINAPI *pWndProc)(HWND,UINT,WPARAM,LPARAM),
LPCTSTR menuName, int x, int y, int width, int height,
UINT classStyle, DWORD windowStyle, HWND hParent)
{
char szClassName[] = "KWndClass";
wc.cbSize
wc.style
wc.lpfnWndProc
wc.cbClsExtra
wc.cbWndExtra
wc.hInstance
wc.hIcon
wc.hCursor
wc.hbrBackground
wc.lpszMenuName
wc.lpszClassName
wc.hIconSm
=
=
=
=
=
=
=
=
=
=
=
=
sizeof(wc);
classStyle;
pWndProc;
0;
0;
hInst;
LoadIcon(NULL, IDI_APPLICATION);
LoadCursor(NULL, IDC_ARROW);
(HBRUSH)GetStockObject(WHITE_BRUSH);
menuName;
szClassName;
LoadIcon(NULL, IDI_APPLICATION);
//
if (!RegisterClassEx(&wc)) {
char msg[100] = "Cannot register class: ";
strcat(msg, szClassName);
MessageBox(NULL, msg, "Error", MB_OK);
return;
}
//
hWnd = CreateWindow(szClassName, windowName, windowStyle,
x, y, width, height, hParent, (HMENU)NULL, hInst, NULL);
if (!hWnd) {
char text[100] = "Cannot create window: ";
strcat(text, windowName);
MessageBox(NULL, text, "Error", MB_OK);
return;
48
1.2 ()
}
//
ShowWindow(hWnd, cmdShow);
}
//////////////////////////////////////////////////////////////////////
// Hello2.cpp
#include <windows.h>
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
MSG msg;
KWnd mainWnd("A Hello2 application", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
int userReply;
switch (uMsg)
{
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rect);
DrawText(hDC, "Hello, World!", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER );
EndPaint(hWnd, &ps);
break;
case WM_CLOSE:
userReply = MessageBox(hWnd, " ?",
"", MB_YESNO | MB_ICONQUESTION);
if (IDYES == userReply)
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
49
:
KWnd 12 .
,
.
,
LRESULT.
WINAPI __stdcall.
, ,
KWnd.
WM_CLOSE
. MessageBox
.
MB_YESNO : YES NO.
YES IDYES,
DestroyWindow.
( Hello2),
.
mainWnd. ,
KWnd mainWnd("Hello application", hInstance, nCmdShow, WndProc, NULL, 50,
100, 200, 150);
.
Hello, World! .
KWnd
.
KWnd, KWnd.h
KWnd.cpp, #include "KWnd.h" , .
Win32 API ,
, . . 1.12
.
50
1.12.
BringWindowToTop
CloseWindow
EnableWindow
FindWindow
GetActiveWindow
GetClassInfo
WNDCLASS
GetClassLong
WNDCLASSEX
GetClientRect
GetFocus
GetParent
GetWindow
GetWindowInfo
WINDOWINFO
GetWindowLong
GetWindowRect
IsChild
IsIconic
IsZoomed
IsWindowEnabled
MoveWindow
SetActiveWindow
SetClassLong
32- WNDCLASSEX ,
SetFocus
SetWindowLong
(
CreateWindow)
SetWindowPos
SetWindowText
ShowWindow
UpdateWindow
WM_PAINT ,
. 1.13 ,
.
51
1.13.
WM_CLOSE
, .
,
DestroyWindow. ( WM_CLOSE ) DefWindowProc DestroyWindow
WM_COMMAND
WM_CREATE
, CreateWindow
CreateWindowEx. ,
, . ,
, , .
. 1, , CreateWindow
NULL
WM_DESTROY
WM_INITDIALOG
1 , . ,
WM_MOVE
WM_PAINT
WM_SIZE
WM_TIMER
, ,
SetTimer,
, , KWnd,
: SetClassLong
SetWindowLong.
SetClassLong,
WNDCLASSEX. ,
RegisterClassEx
.
SetClassLong :
DWORD SetClassLong(
HWND hWnd,
//
int nIndex,
// ,
LONG dwNewLong
//
);
7.
52
nIndex ( ) 1 ,
, , . 1.14.
1.14. nIndex SetClassLong
GCL_HBRBACKGROUND
GCL_HCURSOR
GCL_HICON
GCL_HICONSM
GCL_MENUNAME
GCL_STYLE
GCL_WNDPROC
Hello2,
.
WndProc, switch,
:
case WM_CREATE:
SetClassLong(hWnd, GCL_HBRBACKGROUND,
(LONG) CreateSolidBrush(RGB(200,160,255)));
break;
,
2.
hDC = BeginPaint(hWnd, &ps);
:
SetBkMode(hDC, TRANSPARENT);
Windows
,
.
Windows
, .
UpdateWindow (. . 1.12) ,
Windows WM_PAINT
, .
. ,
, Windows.
1
, cbClsExtra.
Windows
53
, Windows
.
.
, Windows
.
. ,
,
(WM_KEYDOWN WM_KEYUP), (WM_MOUSEMOVE)
(WM_LBUTTONDOWN). ,
(WM_TIMER),
(WM_PAINT) (WM_QUIT).
,
PostMessage.
, , .
. ,
DefWindowProc, Windows ,
. ,
SendMessage.
, (reentrant
program). , Windows WndProc
, DefWindowProc WndProc
.
,
.
, ,
Hello1. ,
Windows WM_SYSCOMMAND
WndProc.
DefWindowProc. DefWindowProc ,
WM_CLOSE .
DestroyWindow.
, DefWindowProc ,
DestroyWindow. DestroyWindow
Windows WM_DESTROY. ,
WndProc, , PostQuitMessage,
WM_QUIT
. WM_QUIT WinMain,
.
.
,
. , ,
, ,
,
.
54
.
,
.
SendMessage
. :
LRESULT SendMessage(
HWND hWnd,
//
UINT Msg,
//
WPARAM wParam, //
LPARAM lParam
//
);
, , .
SendMessage, Windows, ,
hWnd, .
,
Windows , SendMessage.
, ,
,
.
HWND_BROADCAST,
,
.
wParam lParam ,
.
MSDN ,
, WM_PAINT, WM_TIMER, WM_SETFONT
.
SendNotifyMessage
SendNotifyMessage , SendMessage.
, , ,
SendNotifyMessage
SendMessage.
, .
, , ,
SendNotifyMessage
,
.
PostMessage
PostMessage .
, SendMessage.
SendMessage, PostMessage
, , hWnd.
Windows
55
, ,
.
, ,
,
.
. Hello1
GetClientRect.
WM_SIZE.
lParam
, . ,
WndProc:
int width, height;
WM_SIZE,
:
case WM_SIZE:
width = LOWORD(lParam);
height = HIWORD(lParam);
return 0;
LOWORD HIWORD ,
Windows; ,
32 .
GetClientRect
WM_PAINT :
rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
,
.
, WndProc
.
. width height
(static), .
switch, static!
.
Win32 API
. ,
56
hInstance WinMain
.
hInstance WinMain,
, ,
hInstance? .
(, C++)
HINSTANCE hInst;
WinMain hInstance. ,
.
hInst .
GetClassLong:
hInst = (HINSTANCE)GetClassLong(hWnd, GCL_HMODULE);
GetModuleHandle:
hInst = GetModuleHandle(NULL);
,
, .
Windows ,
,
,
.
.
. .
. ,
(, Play)
:
void OnPlay() {
while (!fReadData.eof()) {
fReadData.read(buf, 512);
DoSomething();
// -
}
}
Windows
57
PeekMessage.
GetMessage:
BOOL PeekMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
//
//
//
//
//
,
. ,
, .
wRemoveMsg :
PM_NOREMOVE ;
PM_REMOVE .
, OnPlay, PeekMessage,
:
// -
}
}
PeekMessage ,
, .
ProgressBar,
8.
Spy++
,
Windows .
Visual Studio 6
Spy++.
:
ToolsSpy++.
Spy++ 3.
58
2. GDI
GDI
.
,
,
. 2.1. , GDI
59
GDI
.
(device context) ,
, , .
:
(pen) .
(brush) .
(bitmap) .
(palette) .
(font) .
(region) .
(
),
. ,
Windows
.
GDI, ,
.
,
GDI. GDI
,
.
.
Hello1 DrawText,
,
, ,
,
. , , ,
, ,
.
,
GDI, .
Win32 API :
;
( );
60
2. GDI
, .
, WM_PAINT
Hello1 ( 1). WM_PAINT ,
.
, ,
Windows , ,
,
.
Windows.
Windows
. , ,
, .
,
.
,
1.
Win32 GDI.
(update region), , ,
(invalid region) ,
.
(visible region) ,
. ,
, ,
, .
(clipping region) ,
.
BeginPaint,
.
SetWindowRgn, SelectClipPath SelectClipRgn.
CreateWindow
WS_CLIPCHILDREN WS_CLIPSIBLINGS,
,
.
.
. . Windows
, ( )
.
1
Windows [6].
61
WM_PAINT.
BeginPaint, :
HDC BeginPaint(
HWND hwnd,
LPPAINTSTRUCT lPaint
);
//
// PAINTSTRUCT
.
PAINTSTRUCT,
:
typedef struct tagPAINTSTRUCT {
HDC hdc;
//
BOOL fErase; //
RECT rcPaint; //
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT;
.
rcPaint RECT
.
,
InvalidateRect.
.
fErase , Windows
. fErase TRUE, ()
. InvalidateRect
InvalidateRgn,
.
, BeginPaint
WM_ERASEBKGND. ,
.
DefWindowProc,
, hbrBackground .
, BeginPaint NULL,
, , .
WM_PAINT ,
.
BeginPaint
WM_NCPAINT.
,
. ,
DefWindowProc.
WM_PAINT :
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
[ GDI ]
EndPaint(hWnd, &ps);
return 0;
62
2. GDI
EndPaint, .
WM_PAINT .
WM_ PAINT, . , ,
, (,
GetTextMetrics),
WM_PAINT.
GetDC:
hdc = GetDC(hWnd);
GetWindowDC:
hdc = GetWindowDC(hWnd);
hWnd, . hWnd
NULL,
.
GDI
ReleaseDC, :
hDC = GetDC(hWnd);
[ GDI ]
ReleaseDC(hWnd, hDC);
, , ,
BeginPaint, , GetDC,
, . ,
,
, .
BeginPaint, GetDC
.
,
, , .
WM_PAINT. ,
,
WM_PAINT.
. Win32
API ,
1.
1
,
16 Windows
32 .
63
, BeginPaint, GetDC, GetWindowDC, (common),
(private) ,
( style WNDCLASS).
,
.
,
, .
Windows
.
.
.
,
, .
CS_OWNDC style
WNDCLASS .
.
,
.
,
.
,
(CAD), ,
.
WM_PAINT
, WM_PAINT.
,
. ,
:
;
, ;
.
,
WM_PAINT , InvalidateRect, InvalidateRgn
UpdateWindow.
UpdateWindow WM_PAINT
, .
WM_PAINT
,
64
2. GDI
Windows. ,
, , ,
.
, WM_PAINT. ,
: ,
.
InvalidateRect InvalidateRgn
WM_PAINT
,
InvalidateRect InvalidateRgn.
InvalidateRect :
BOOL IvalidateRect(HWND hWnd, CONST RECT* lpRect, BOOL bErase);
:
hWnd , .
NULL,
, WM_ERASEBKGND WM_NCPAINT
.
lpRect RECT,
, .
NULL,
.
bErase , , .
TRUE, ,
BeginPaint. FALSE, .
. ,
. TRUE,
FALSE,
. ,
. ,
rcUpdate,
, NULL.
InvalidateRgn :
, , ,
. hRgn ,
.
CreateRectRgn, CreatePolygonRgn ,
.
, InvalidateRect, InvalidateRgn
, .
, hWnd WM_PAINT.
,
WM_PAINT DefWindowProc.
:
65
case WM_PAINT:
return 0; // !!!
, , , Windows
WM_PAINT .
BeginPaint,
. Windows WM_PAINT.
, .
, CreateDC.
, , ,
.
,
. ,
DeleteDC.
( )
, .
,
.
, .
( )
.
, :
HDC CreateCompatibleDC (HDC hdc);
hdc
, .
NULL, ,
.
,
.
, .
,
.
, (bitmap)
. SelectObject
CreateCompatibleBitmap.
: , ,
.
,
, DeleteDC.
3.
66
2. GDI
,
, .
GDI.
GDI .
,
.
,
,
,
,
.
3.
.
, ,
, ,
GDI.
CreateIC,
:
HDC CreateIC(
LPCTSTR lpszDriver,
LPCTSTR lpszDevice,
LPCTSTR lpszOutput,
CONST DEVMODE* lpDvm
);
//
//
//
//
DEVMODE
Win32
NULL.
DEVMODE,
.
,
, DeleteDC.
,
.
.
(x, y). x , y
. .
67
(screen coordinates),
. RECT,
.
(window coordinates),
(client coordinates) (. . 1.3).
Win32 GDI,
,
MSDN.
.
, , ,
.
.
Win32 GDI
, ,
, .
(world space)
, .
(page space)
,
, .
.
(device space)
. ,
.
. 2.2.
68
2. GDI
. .
X , Y .
227 227 .
1.
. , GetWindowRect
.
, WM_NCMOUSEMOVE.
.
, ,
. ,
, .
GetDeviceCap.
(device coordinates)
.
.
, CreateDC, CreateIC Create
CompatibleDC,
.
, (
GetDC, GetWindowDC BeginPaint),
.
,
(0, 0), X , Y
. ,
GetDCOrgEx.
,
,
( ). Win32 API
:
BOOL ClientToScreen(HWND hWnd, LPOINT lpPoint);
BOOL ScreenToClient(HWND hWnd, LPOINT lpPoint);
.
, , WM_MOUSEMOVE WM_ LBUTTON DOWN.
1
. , .
69
.
,
.
, Win32
GDI
, .
, .
Win32 API
. ,
16 Windows
Win32 Windows 95/98. ,
, Windows NT/2000.
Windows
.
:
(window);
(viewport).
,
,
.
.
. ,
, .
.
.
(window)
:
xWO (xorigin).
yWO (yorigin).
xWE (xextent).
yWE (yextent).
(viewport)
:
xVO (xorigin).
yVO (yorigin).
xVE (xextent).
yVE (yextent).
70
2. GDI
. (0, 0, 1, 1),
(dx, dy, 1, 1). x' = x + dx, y' = y + dy.
(dx, dy).
. (0, 0, 1, 1),
(0, 0, mx, my). x' = x mx, y' = y my.
(mx, my).
. (0, 0, w, h),
(w, h, w, h). x' = w x, y' = h y.
.
,
.
.
Win32 API
:
BOOL SetWindowOrgEx (
HDC hdc,
//
int X,
//
int Y,
//
LPPOINT lpPoint //
//
);
BOOL SetWindowExtEx (
HDC hdc,
//
int nXExtent,
//
int nYExtent,
//
LPSIZE lpSize
//
//
);
x-
y-
POINT
X
Y
SIZE
, ,
. ,
.
:
BOOL SetViewportOrgEx (
HDC hdc,
//
71
int X,
// X-
int Y,
// Y-
LPPOINT lpPoint //
);
BOOL SetViewportExtEx
HDC hdc,
//
int nXExtent,
//
int nYExtent,
//
LPSIZE lpSize
//
);
(
X
Y
NULL, .
SetWindowOrgEx SetViewportOrgEx
. ,
(0, 0) 1.
, ,
(0, 0) . ,
! ,
.
2.3.
Win32 API
, (mapping modes).
.
. ,
,
.
:
int SetMapMode (HDC hDC, int iMapMode);
iMapMode
, . 2.1.
2.1.
MM_TEXT
MM_LOMETRIC
0,1
MM_HIMETRIC
0,01
MM_LOENGLISH
0,01
MM_HIENGLISH
0,001
MM_TWIPS
1 / 1440
MM_ISOTROPIC
(x == y)
MM_ANISOTROPIC
(x != y)
, (0, 0)
.
72
2. GDI
SetMapMode ,
MM_TEXT.
,
.
, , , ,
. ,
SetPixel
1 .
CreatePen nWidth .
.
( 2.3).
,
Win16 GDI API:
,
.
API. ,
Y. ,
X , .
.
,
. ,
GDI .
Windows NT/2000
.
32 ,
.
, Windows NT/2000,
.
, .
,
2 3. Win32 API
XFORM:
typedef struct _XFORM {
FLOAT eM11;
FLOAT eM12;
FLOAT eM21;
FLOAT eM22;
FLOAT eDx;
FLOAT eDy;
} XFORM;
73
, ,
(x, y) (x', y') :
x' = eM11 x + eM21 y + eDx;
y' = eM12 x + eM22 y + eDy.
:
. (1, 0, 0, 1, 0, 0).
x' = x, y' = y.
. (1, 0, 0, 1, 0, 0).
x' = x, y' = y.
. (1, s, 0, 1, 0, 0)1.
x' = x + s y y' = y.
.
.
Win32 API
(Windows NT/2000)
. 16
GDI. ,
.
SetGraphicsMode
(hDC, GM_ADVANCED).
, .
,
SetGraphicsMode(hDC, GM_COMPATIBLE).
, SaveDC RestoreDC.
.
:
BOOL SetWorldTransform(HDC hDC, CONST XFORM* lpXform);
BOOL ModifyWorldTransform(HDC hDC, CONST XFORM* lpXform, DWORD iMode);
SetWorldTransform
, XFORM.
1
x , y.
74
2. GDI
ModifyWorldTransform iMode
:
MTW_IDENTIFY ;
MTW_LEFTMULTIPLY
lpXform ;
MTW_RIGHTMULTIPLY
lpXform .
GetWorldTransform.
12.
. GetDeviceCaps,
, :
int GetDeviceCaps(HDC hdc, int nIndex);
nIndex . 2.21.
2.2. nIndex
DRIVERVERSION
TECHNOLOGY
HORZSIZE
VERTSIZE
HORZRES
VERTRES
LOGPIXELSX
LOGPIXELSY
BITSPIXEL
PLANES
NUMBRUSHES
NUMPENS
NUMFONTS
NUMCOLORS
CLIPCAPS
SIZEPALETTE
. MSDN.
75
COLORRES
PHYSICALWIDTH
( )
PHYSICALHEIGHT
( )
PHYSICALOFFSETX
PHYSICALOFFSETY
RASTERCAPS
.
: RC_BITBLT
; RC_BITMAP64
,
64 ; RC_DEVBITS ; RC_NONE
; RC_PALETTE ,
; RC_SCALING ;
RC_STRETCHBLT StretchBlt;
RC_STRETCHDIB StretchDiBIts
CURVECAPS
.
: CC_CHORD
; CC_CIRCLES
; CC_ELLIPSWS ;
CC_INTERIORS ;
CC_NONE
LINECAPS
.
: LC_STYLED
; LC_WIDE
; LC_POLYLINE
; LC_INTERIORS ;
LC_NONE
POLYGONALCAPS
.
:
PC_STYLED ;
PC_WIDE ; PC_POLYGON
; PC_INTERIORS
; PC_NONE
TEXTCAPS
.
: TC_CR_90
90; TC_CR_ANY
; TC_EA_DOUBLE
; TC_IA_ABLE
; TC_RA_ABLE
; TC_VA_ABLE
, 1
,
, WM_CREATE:
HDC hdc = GetDC(hwnd);
int logPixelY = GetDeviceCaps(hdc, LOGPIXELY);
// logPixelY ...
ReleaseDC(hwnd, hdc);
76
2. GDI
.
.
, .
,
.
, ,
, , , ,
. 0 (
) 255 ( ).
.
,
RGB, : Red (
), Green ( ) Blue (
).
.
, CMYK,
, ,
.
,
.
HLS.
HLS
HLS (Hue),
(Lightness) (Saturation).
0 360.
, 60 , 120 , 180 , 240
, 300 .
.
. ,
, .
, ,
. ,
.
.
RGB
Windows RGB
, .
COLORREF, .
: 0 RGB, 1 PALETTEINDEX, 2 PALETTERGB.
RGB . 2.3.
77
(0) .
(255) .
RGB, 224
, 16,7 .
Win32 API ,
RGB 32 COLORREF , ,
COLORREF RGB.
, wingdi.h,
(inline) :
COLORREF RGB(BYTE byRed, BYTE byGreen, BYTE byBlue);
BYTE GetRValue(COLORREF rgb);
BYTE GetGValue(COLORREF rgb);
BYTE GetBValue(COLORREF rgb);
RGB
, :
const
const
const
const
const
const
const
const
COLORREF
COLORREF
COLORREF
COLORREF
COLORREF
COLORREF
COLORREF
COLORREF
black
red
green
blue
yellow
magenta
cyan
white
=
=
=
=
=
=
=
=
RGB(0, 0, 0);
RGB(255, 0, 0);
RGB(0, 255, 0);
RGB(0, 0, 255);
RGB(255, 255, 0);
RGB(255, 0, 255);
RGB(0, 255, 255);
RGB(255, 255, 255);
//
//
//
//
//
//
//
//
, 16 777 216
RGB COLORREF. ,
, 256 .
.
3.
COLORREF, .
Win32 API PALETTEINDEX PALETTERGB,
COLORREF.
. 2.4.
78
2. GDI
:
COLORREF GetPixel(HDC hdc, int X, int Y);
BOOL SetPixelV(HDC hdc, int X, int Y, COLORREF color);
COLORREF SetPixel(HDC hdc, int X, int Y, COLORREF color);
X Y .
color, ,
RGB1.
GetPixel
.
SetPixelV SetPixel
, .
, , .
,
, 1.
, , SetPixelV SetPixel
.
NtGdiSetPixel, , ,
:
;
COLORREF ;
DrvBitBlt;
.
[6] ,
1000 .
, GetPixel 6000
.
, ,
.
12.
,
,
,
.
, RGB
PALETTERGB.
79
.
. SetPixel(hDC, x,
y, color), x y color.
SetPixel .
, , ,
.
Windows
.
S ( ) D (
).
(, SetPixel)
f(D, S),
:
D = f(D, S).
, , GDI
.
, , ,
. Windows ,
, (raster operation
(ROP)). ,
(binary raster operation (ROP2)).
MSDN
P,
:
D = f(D, P).
, . 2.3,
,
SetPixel.
2.3.
P:
D:
1100
1010
ROP2
0000
0001
0010
D=0
D = ~(D | P)
D = D & ~P
R2_BLACK
R2_NOTMERGEPEN
R2_MASKNOTPEN
0011
0100
D = ~P
D = P & ~D
R2_NOTCOPYPEN
R2_MASKPENNOT
0101
0110
D = ~D
D=D^P
R2_NOT
R2_XORPEN
0111
1000
D = ~(D & P)
D=D&P
R2_NOTMASKPEN
R2_MASKPEN
0 ( )
R2_MERGEPEN
R2_MASKPEN
80
2. GDI
2.3 ()
P:
D:
1100
1010
ROP2
1001
1010
1011
D = ~(D ^ P)
D=D
D = D | ~P
R2_NOTXORPEN
R2_NOP
R2_MERGENOTPEN
1100
1101
D=P
D = P | ~D
R2_COPYPEN
R2_MERGEPENNOT
1110
1111
D=P|D
D=1
R2_MERGEPEN
R2_WHITE
R2_XORPEN
( )
1 ( )
GDI ,
(drawing mode). ROP2.
SetROP2:
int SetROP2(HDC hdc, int fnDrawMode);
fnDrawMode ROP2,
. 2.3. .
GetROP2.
R2_COPYPEN,
.
,
RGB,
RGB.
,
. ,
(RGB(0xFF, 0, 0)) R2_XORPEN,
(RGB(0xFF, 0xFF, 0xFF))
(cyan),
RGB(0, 0xFF, 0xFF). ,
,
.
R2_XORPEN .
, .
.
R2_BLACK ,
R2_WHITE . R2_NOTCOPYPEN
. R2_NOP ,
.
R2_XORPEN R2_NOTXORPEN
. , ,
.
,
.
R2_XORPEN R2_NOTXORPEN
,
81
.
.
GDI :
(foreground) (background). ,
, 1 , ,
2 .
,
.
,
.
. (background color)
,
SetBkColor.
.
,
, , .
.
Hello1 .
.
,
,
(background mix mode)3.
OPAQUE4.
, Windows ( background
color) . ,
.
SetBkMode, TRANSPARENT5.
, ,
GetBkMode.
, GDI ,
.
1
(glyph) .
82
2. GDI
, , , , .
:
1. .
2. .
3. , .
4. , .
5. .
GDI Create,
.
SelectObject ( SelectPalette).
SelectObject :
HGDIOBJ SelectObject(
HDC hdc,
//
HGDIOBJ hgdiobj
// GDI-
);
hgdiobj
hdc.
.
( 3)
( 4).
, , Delete
Object.
, GDI
Create.
() ,
(, , . .) ,
GetStockObject.
DeleteObject.
.
,
SetPixel x y. ,
, , ,
.
,
, . Win32 GDI
.
83
Windows ,
.
1 .
.
.
POINT.
(0, 0). ,
MoveToEx:
BOOL MoveToEx(
HDC hdc,
int X,
int Y,
LPPOINT lpPoint
);
//
//
//
//
x-
y-
,
NULL.
.
,
GetCurrentPositionEx(hDC, &pt);
pt POINT.
LineTo:
BOOL LineTo(
HDC hdc,
//
int xEnd, // x-
int yEnd
// y-
);
, ,
, (xEnd, yEnd), .
.
, ,
(xEnd, yEnd).
,
. , ,
, ,
, :
{
POINT pt[5] = {{100,100}, {200,100}, {200,200},
{100,200}, {100,100}};
MoveToEx(hDC, pt[0].x, pt[0].y, NULL);
for (int i = 0; i < 5; ++i)
LineTo(hDC, pt[i].x, pt[i].y);
}
84
2. GDI
Hello2 ( 1)
DrawText, , .
switch.
( )
Polyline:
BOOL Polyline(HDC hdc, CONST POINT* lppt, int cPoints);
,
.
:
{
POINT pt[5] = {{100,100}, {200,100}, {200,200},
{100,200}, {100,100}};
Polyline(hDC, pt, 5);
}
, ,
Polyline .
PolylineTo
:
BOOL PolylineTo(HDC hdc, CONST POINT* lppt, DWORD cPoints);
. ,
Polyline :
MoveToEx(hDC, pt[0].x, pt[0].y, NULL);
PolylineTo(hDC, pt + 1, 4);
PolyPolyline
. :
BOOL PolyPolyline(
HDC hdc,
CONST POINT* lppt,
CONST DWORD* lpPolyPoints,
DWORD cCount
);
//
//
//
//
Windows .
.
.
(xLeft, yTop) (xRight, yBottom),
(x0, y0), x0 = xLeft + (xRight xLeft)/2, y0 = yTop + (yBottom yTop)/2.
Arc, ArcTo AngleArc.
,
Arc:
85
BOOL Arc(HDC hdc, int xLeft, int yTop, int xRight, int yBottom,
int xStart, int yStart, int xEnd, int yEnd);
. ,
(xStart, yStart)
(xEnd, yEnd). ,
(xStart, yStart).
,
(xEnd, yEnd). .
Windows 95/98 . Windows NT/2000
, GetArcDirection
SetArcDirection.
SetArcDirection, :
AD_COUNTERCLOCKWISE,
, AD_CLOCKWISE, .
AD_ COUNTERCLOCKWISE.
. 2.5 ,
Arc(hDC, 100, 100, 400, 300, 350, 50, 50, 300);
. 2.5. , Arc (
)
Arc
SetArcDirection(hDC, AD_CLOCKWISE);
Arc , . 2.6.
Arc .
ArcTo Arc ,
,
.
.
AngleArc, Windows NT/2000,
,
:
BOOL AngleArc(HDC hdc, int X, int Y, DWORD radius, FLOAT startAngle,
FLOAT sweepAngle);
86
2. GDI
. 2.6. , Arc ( )
X Y , radius . ,
, . ,
.
startAngle ,
sweepAngle . ,
, .
sweepAngle ,
.
AngleArc, ArcTo,
,
.
, , Windows
, .
( ) ,
p1, p2, p3 p4. p1
, p4 . p2, p3
,
, , p1 p4.
2.7.
. 2.7.
87
.
(P.Bezier)
. ,
.
Win32 GDI ,
:
BOOL PolyBezier(HDC hdc, CONST POINT* lppt, DWORD cPoints);
BOOL PolyBezierTo(HDC hdc, CONST POINT* lppt, DWORD cCount);
n PolyBezier lppt,
3n + 1 , cPoints
3n + 1. , lppt[0], lppt[1], lppt[2], lppt[3],
. lppt[3]
. . PolyBezier
.
PolyBezier, PolyBezierTo 3n lppt,
cCount 3n. ,
, , ,
.
, PolyBezier.
lppt.
[6].
,
(pen), .
, BLACK_PEN.
1
. ,
, , ,
!
Win32 GDI
.
.
,
.
, ,
.
GDI,
.
.
GDI HGDIOBJ;
HPEN (handle to a pen).
, HGDIOBJ Windows
void, HPEN
88
2. GDI
. , HPEN
HGDIOBJ, HGDIOBJ HPEN
.
, hPen :
HPEN hPen;
.
.
, GDI,
. , ,
DeleteObject1.
Win32 GDI ,
. 2.4.
2.4.
BLACK_PEN
WHITE_PEN
NULL_PEN
( )
DC_PEN
DC 1 .
.
SetDCPenColor
Windows 2000
GetStockObject, ,
:
hPen = (HPEN)GetStockObject(WHITE_PEN);
GetStockObject HGDIOBJ,
.
,
:
SelectObject(hDC, hPen);
, , WHITE_PEN
,
.
hPen,
GetStockObject SelectObject :
SelectObject(hDC, GetStockObject(WHITE_PEN));
89
, , :
HPEN hOldPen = (HPEN)SelectObject(hDC, GetStockObject(WHITE_PEN));
// ... WHITE_PEN
//
SelectObject(hDC, hOldPen);
DC, GetStockObject(DC_PEN),
GDI. GDI
. , ,
. GDI,
.
.
DC ,
.
SetDCPenColor, :
COLORREF SetDCPenColor(HDC hdc, COLORREF crColor);
crColor DC.
DC.
,
:
{
HGDIOBJ hOld = SelectObject(hDC, GetStockObject(DC_PEN));
for (int i = 0; i < 256; ++i) {
SetDCPenColor(hDC, RGB(255-i, 128, i));
MoveToEx(hDC, 10, i+10, NULL);
LineTo(hDC, 266, i+10);
}
SelectObject(hDC, hOld);
}
Hello2 ( 1)
DrawText, 1.
, 2, .
, DC_PEN .
, (
#include <windows.h>) :
#define
_WIN32_WINNT
0x500
.
,
1
switch.
90
2. GDI
. CreatePen
CreatePenIndirect.
CreatePen :
HPEN CreatePen(int fnPenStyle, int nWidth, COLORREF crColor);
,
.
. 2.5.
2.5.
PS_SOLID
PS_DASH
nWidth <= 1
PS_DOT
nWidth <= 1
PS_DASHDOT
nWidth <= 1
PS_DASHDOTDOT
nWidth <= 1
PS_NULL
PS_INSIDEFRAME
nWidth > 1
. 2.8 , .
1 .
. 2.8.
CreatePen
. ,
MM_TEXT,
.
,
,
, .
,
. ,
.
, .
nWidth .
1 .
(PS_DASH, PS_DOT, PS_DASHDOT,
PS_DASHDOTDOT) , Windows
PS_SOLID. , ()
1 . ,
.
91
CreatePen
COLORREF. RGB,
PALETTERGB1. ,
, 24 RGB
, ,
. ( PALETTERGB) ,
, , ,
256 . Windows
RGB .
, ,
,
, . ,
PS_INSIDEFRAME, ,
. PS_INSIDEFRAME
. ,
nWidth , . ,
. 2.5 2.6 PS_INSIDEFRAME.
nWidth , PS_INSIDEFRAME
PS_SOLID.
CreatePen.
() 5
:
hPen = CreatePen(PS_SOLID, 5, RGB(255, 0, 0));
,
. , nWidth
.
CreatePenIndirect:
HPEN CreatePenIndirect(CONST LOGPEN* lplgpn);
LOGPEN:
typedef struct tagLOGPEN
UINT
style; //
POINT
width; //
COLORREF color; //
} LOGPEN;
, :
logpen.style = PS_SOLID;
logpen.width.x = 10;
logpen.color = RGB(255, 0, 0);
CreatePenIndirect:
hPen = CreatePenIndirect(&logpen);
. . .
92
2. GDI
, CreatePenIndirect,
, , CreatePen.
, CreatePen CreatePenIndirect
. ,
, SelectObject.
.
, : 2,
5 .
:
static HPEN hPen1, hPen2, hPen3;
WM_CREATE:
hPen1 = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
hPen2 = CreatePen(PS_SOLID, 5, RGB(0, 255, 0));
hPen3 = CreatePen(PS_DASH, 1, RGB(0, 0, 255));
WM_PAINT
:
SelectObject(hDC, hPen1);
// ...
SelectObject(hDC, hPen2);
// ...
WM_DESTROY
:
DeleteObject(hPen1);
DeleteObject(hPen2);
DeleteObject(hPen3);
. . ,
WM_PAINT
EndPaint .
, ,
CreatePen SelectObject :
SelectObject(hDC, CreatePen(PS_DOT, 0, RGB(255, 255, 0)));
. , .
, ?
SelectObject ,
. ,
BLACK_PEN ,
SelectObject:
DeleteObject(SelectObject(hDC, GetStockObject(BLACK_PEN)));
.
, SelectObject:
hPen = SelectObject(hDC, CreatePen(PS_DOT, 0, RGB(255, 255, 0)));
SelectObject
, hPen BLACK_PEN.
:
DeleteObject(SelectObject(hDC, hPen));
93
, ,
. , 1
, ,
.
Win32 API
ExtCreatePen, :
HPEN ExtCreatePen(
DWORD dwPenStyle,
DWORD dwWidth,
CONST LOGBRUSH* lplb,
DWORD dwStyleCount,
CONST DWORD* lpStyle
);
//
//
//
//
//
lpStyle
,
dwPenStyle ,
, ,
. . 2.62.9.
2.6.
PS_COSMETIC
. 1
PS_GEOMETRIC
. 2.6 ,
.
2.7.
PS_ALTERNATE
Windows NT/2000
PS_SOLID
PS_DASH
Windows 95:
. Windows 98:
PS_DOT
Windows 95/98:
PS_DASHDOT
Windows 95:
. Windows 98:
PS_DASHDOTDOT
Windows 95:
. Windows 98:
PS_NULL
PS_INSIDEFRAME
PS_USERSTYLE
dwStyleCount lpStyle
Windows NT/2000
94
2. GDI
, PS_INSIDEFRAME, .
.
2.8. ,
PS_ENDCAP_ROUND
PS_ENDCAP_SQUARE
PS_ENDCAP_FLAT
2.9. ,
PS_JOIN_BEVEL
PS_JOIN_MITER
PS_JOIN_ROUND
1 .
Windows PS_SOLID.
PS_DASH, PS_DOT, PS_DASHDOT PS_DASHDOTDOT
, . ,
, ,
OPAQUE.
PS_ALTERNATE
, 1
1 .
PS_USERSTYLE
: dwStyleCount lpStyle.
,
, . .
.
, ,
, , .
.
, , 3
, MM_TEXT
1 .
, , .
.
,
, . 2.9.
,
, PS_ENDCAP_ROUND. ,
ExtCreatePen
95
. 2.8. . 2.10 , Z,
.
LineTo.
, . ,
, .
. 2.9. 10
. 2.10.
, LineTo
R2_XORPEN,
, . 2.11, .
Z , Polyline ( . 2.11
), .
.
lbStyle LOGBRUSH
BS_HATCHED, lbHatch HS_DIAGCROSS1.
. 2.11. R2_XORPEN
Polyline GDI,
.
, .
,
. 2.9.
PS_JOIN_ROUND. . 2.12
.
Polyline.
1
96
2. GDI
. 2.12. Polyline
.
, ,
Windows ,
. ,
, , (
) .
, .
, ,
, .
, ,
.
8 8 ,
. Windows
(dithering) ,
, .
, ,
64 .
,
.
Win32 GDI
. ,
.
.
, .
.
97
HBRUSH (handle to
a brush), :
HBRUSH hBrush;
.
. ,
SelectObject,
.
,
, DeleteObject.
.
.
, GDI, . 2.10.
2.10.
BLACK_BRUSH
DKGRAY_BRUSH
DC_BRUSH
GRAY_BRUSH
HOLLOW_BRUSH
LTGRAY_BRUSH
NULL_BRUSH
-
DC ; ;
SetDCBrushColor
( )
-
, HOLLOW_BRUSH
WHITE_BRUSH
, , , 8 8
. DC, Windows 2000,
GDI. DC, DC
.
SetDCBrushColor.
,
GetStockObject , . 2.10, :
hBrush = (HBRUSH) GetStockObject(GRAY_BRUSH);
,
. Windows
, : ,
.
CreateSolidBrush:
HBRUSH CreateSolidBrush(COLORREF crColor);
98
2. GDI
crColor
COLORREF. RGB PALETTERGB1.
,
, 24 RGB.
.
, .
Windows PALETTERGB
. ,
,
(dithering).
3 6.
CreateHatchBrush:
HBRUSH CreateHatchBrush(int fnStyle, COLORREF clrref);
fnStyle, ,
HS_HORIZONTAL, HS_VERTICAL, HS_BDIAGONAL, HS_FDIAGONAL, HS_CROSS HS_DIAGCROSS.
. 2.13 ,
64 64 ( ).
,
. 8 8
.
. 2.13.
. . 2.13
.
clrref,
,
SetBkColor.
, OPAQUE.
GDI
SetBrushOrgEx:
BOOL SetBrushOrgEx(HDC hdc, int nXOrg, int nYOrg, LPPOINT lppt);
(nXOrg, nYOrg), ,
.
. lppt
POINT, .
(0, 0).
1
. . .
99
, , 1
, . ,
,
xLeft yTop .
,
.
( ) CreatePatternBrush:
HBRUSH CreatePatternBrush(HBITMAP hbmp);
hbmp GDI.
GDI (bitmap),
(DDB)1, ,
.
.
MS Paint 32 32 ,
, . 2.14.
Star.bmp.
. 2.14. , MS Paint
Hello2, ,
:
{
HBITMAP hBmp = (HBITMAP)LoadImage(NULL, "Star.bmp", IMAGE_BITMAP, 0,
0, LR_LOADFROMFILE);
HBRUSH hBrush = CreatePatternBrush(hBmp);
HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
Rectangle(hDC, 32, 32, 288, 160);
DeleteObject(SelectObject(hDC, hOldBrush));
}
LoadImage
(DIB)2 Star.bmp,
GDI hBmp.
CreatePatternBrush, . hBrush
1
3.
3.
100
2. GDI
, Rectangle1.
Star.bmp,
Hello2.
, . 2.15.
. 2.15.
Windows 95/98
. 8 8
. 8 8
.
11.
LOGBRUSH CreateBrushIndirect
Win32 GDI CreateBrushIndirect,
:
HBRUSH CreateBrushIndirect(CONST LOGBRUSH* lplb);
lplb LOGBRUSH,
:
typedef struct tagLOGBRUSH {
UINT
lbStyle;
COLORREF lbColor;
LONG
lbHatch;
} LOGBRUSH;
lbStyle ,
. 2.11.
2.11. lbStyle
BS_SOLID
BS_HATCHED
BS_HOLLOW
BS_NULL
BS_PATTERN
( )
, BS_HOLLOW
,
, BS_PATTERN
, -
(DIB device-independent bitmap),
lbHatch
BS_PATTERN8X8
BS_DIBPATTERN
, , .
101
BS_DIBPATTERN8X8
, BS_DIBPATTERN
BS_DIBPATTERNPT
, -
(DIB). lbHatch DIB
lbColor .
lbStyle . 2.12.
2.12. lbColor
lbStyle
lbColor
BS_HOLLOW BS_PATTERN
BS_HATCHED BS_SOLID
COLORREF
BS_DIBPATTERN BS_DIBPATTERNPT
lbColor
DIB_PAL_COLORS DIB_RGB_COLORS.
, bmiColors,
BITMAPINFO, 16-
, ,
bmiColors RGB-
lbHatch .
lbStyle . 2.13.
2.13. lbHatch
lbStyle
lbHatch
BS_SOLID BS_HOLLOW
BS_PATTERN
GDI (bitmap)
BS_HATCHED
HS_HORIZONTAL, HS_VERTICAL,
HS_BDIAGONAL, HS_FDIAGONAL, HS_CROSS, HS_DIAGCROSS
BS_DIBPATTERN
DIB-
BS_DIBPATTERNPT
DIB-
LOGBRUSH ,
. , . 2.11
.
, Windows
, , ,
.
.
Windows
.
102
2. GDI
, ,
. Win32 API
,
.
1,
:
typedef
LONG
LONG
LONG
LONG
} RECT;
struct tagRECT {
left;
top;
right;
bottom;
(left, top)
(right, bottom) .
, :
RECT rect;
rect
:
rect.left = x_left;
rect.top = y_top;
rect.right = x_right;
rect.bottom = y_bottom;
SetRect, :
BOOL SetRect(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom);
:
SetRect(&rect, x_left, y_top, x_right, y_bottom);
Win32 API
RECT. . 2.14 .
2.14. RECT
X
dX Y dY
SetRectEmpty(&rect);
rect
CopyRect(&DestRect, &SrcRect);
bEmpty = IsRectEmpty(&rect);
, point
rect
103
Rectangle, FillRect,
FrameRect, InvertRect DrawFocusRect.
Rectangle
Rectangle :
BOOL Rectangle(HDC hdc, int xLeft, int yTop, int xRight, int yBottom);
, .
xLeft yTop , xRight yBottom
. .
.
MSDN , xLeft < xRight
yTo p < yBottom, ,
,
, Windows
.
,
:
, (GM_COMPATIBLE)
(GM_ADVANCED);
( ).
2.16 Rectangle
.
. 2.16. Rectangle
,
, , (GRAY_BRUSH),
.
, ,
1, ,
(xRight 1, yBottom 1).
1
. .
104
2. GDI
, , .
,
,
(xRight, yBottom).
PS_NULL,
.
,
. nWidth ,
, (nWidth 1)/2
. ,
nWidth (nWidth 1)
?
.
,
PS_INSIDEFRAME. .
.
, .
, .
FillRect
FillRect :
BOOL FillRect(HDC hdc, CONST RECT* lprc, HBRUSH hbr);
, RECT,
lprc. ,
hbr.
(lprc.right 1, lprc.bottom 1),
.
:
,
;
.
FrameRect
FrameRect :
BOOL FrameRect(HDC hdc, CONST RECT* lprc, HBRUSH hbr);
lprc hbr.
.
, , .
.
, ,
, .
105
FrameRect,
1.
InvertRect
InvertRect :
BOOL InvertRect(HDC hdc, CONST RECT* lprc);
.
,
. ,
, RGB .
InvertRect
.
DrawFocusRect
DrawFocusRect :
BOOL DrawFocusRect(HDC hdc, CONST RECT* lprc);
FrameRect,
.
.
Win32 API,
. , DrawFocusRect
,
. ,
DrawFocusRect.
DrawFocusRect
.
,
,
Win32 GDI ,
,
.
Ellipse,
:
BOOL Ellipse(HDC hdc, int xLeft, int yTop, int xRight, int yBottom);
,
xLeft, yTop, xRight, yBottom.
Ellipse.
1
. PS_ALTERNATE .
106
2. GDI
Arc. ,
, .
Chord:
BOOL Chord(HDC hdc, int xLeft, int yTop, int xRight, int yBottom,
int xStart, int yStart, int xEnd, int yEnd);
, Arc.
(xStart, yStart)
(xEnd, yEnd). , ,
, Arc. . 2.17
Chord.
. 2.17. Chord
, ,
.
Pie, :
BOOL Pie(HDC hdc, int xLeft, int yTop, int xRight, int yBottom,
int xStart, int yStart, int xEnd, int yEnd);
, Arc.
,
Arc. . 2.18 Pie.
RoundRect,
:
BOOL RoundRect(HDC hdc, int xLeft, int yTop, int xRight, int yBottom,
int roundWidth, int roundHeight);
,
.
Rectangle.
, ,
. 2.19.
107
. 2.18. Pie
. 2.19. , RoundRect
roundWidth roundHeight ,
RoundRect . roundWidth xRight xLeft
roundHeight yBottom yTop, RoundRect
.
.
Polygon:
BOOL Polygon(HDC hdc, CONST POINT* lpPoints, int nCount);
Polyline.
,
. Polyline, Polygon
. Polygon,
Polyline, .
.
, , , ,
108
2. GDI
.
. Win32 GDI
: ALTERNATE WINDING.
, ,
SetPolyFillMode.
ALTERNATE. . 2.20
.
. 2.20. , :
ALTERNATE; WINDING
ALTERNATE
:
1.
.
2.
.
3.
, .
, . 2.21.
WINDING
:
1.
.
2. count
.
3.
.
, count
, , .
4. count ,
, .
, . 2.21.
PolyPolygon:
BOOL PolyPolygon(HDC hdc, CONST POINT* lpPoints, CONST int* lpPolyCounts,
int nCount);
. .
109
.
. 2.21.
: ALTERNATE; WINDING
,
.
. ,
.
.
.
, .
. ,
, , , GDI.
,
HRGN. ,
DeleteObject.
, .
.
:
HRGN hRgn;
:
hRgn = CreateRectRgn(xLeft, yTop, xRight, yBottom);
hRgn = CreateRectRgnIndirect(&rect);
, :
hRgn = CreateEllipticRgn(xLeft, yTop, xRight, yBottom);
hRgn = CreateEllipticRgnIndirect(&rect);
110
2. GDI
:
hRgn = CreateRoundRectRgn(xLeft, yTop, xRight, yBottom, roundWidth,
roundHeight);
Polygon:
hRgn = CreatePolygonRgn(point, iCount, iPolyFillMode);
PolyPolygon.
,
.
. 2.15 , .
2.15.
, (X, Y)
hrgn
BOOL RectInRegion(HRGN hrgn, CONST RECT *lprc); ,
lprc hrgn
BOOL EqualRgn(HRGN hRgn1, HRGN hRgn2);
, hRgn1
hRgn2
int GetRgnBox(HRGN hrgn, LPRECT lprc);
lprc
int CombineRgn(HRGN hrgnDest, HRGN hrgnSrc1,
, hrgnSrc1
HRGN hrgnSrc2, int fnCombineMode);
hrgnSrc2,
fnCombineMode.
hrgnDest
int OffsetRgn(HRGN hrgn, int nXOffset, int nYOffset); hrgn
nXOffset X nYOffset
Y
DWORD GetRegionData(HRGN hRgn,
lpRgnData
DWORD dwCount, LPRGNDATA lpRgnData);
RGNDATA ,
hRgn
HRGN ExtCreateRegion(CONST XFORM *lpXform,
RGNDATA
DWORD nCount, CONST RGNDATA *lpRgnData);
,
XFORM
.
PtInRegion
,
. ,
, PtInRegion
WM_MOUSEMOVE .
111
OffsetRgn
. ,
,
, .
CombineRgn
, .
, hrgnDest.
,
, hrgnDest, ,
. fnCombineMode
, , . 2.16.
2.16. , CombineRgn
fnCombineMode
RGN_AND
RGN_OR
RGN_XOR
RGN_DIFF
hrgnSrc1, hrgnSrc2
RGN_COPY
hrgnSrc1
, hrgnSrc1 hrgnDest
, hrgnSrc1.
CombineRgn
.
. 2.17.
2.17. , CombineRgn
NULLREGION
SIMPLEREGION
COMPLEXREGION
ERROR
(
)
, hrgn,
, . 2.18.
.
, . ,
GDI (
, ),
.
, .
,
112
2. GDI
.
, ,
.
CombineRgn.
2.18.
hbr
hbr.
nWidth,
nHeight
(
InvertRect)
. , Windows
, :
( ) ,
.
, InvalidateRect
InvalidateRgn.
,
.
.
, .
,
. ,
, SetWindowRgn SelectClipRgn.
,
.
SetWindowRgn .
, Windows .
:
int SetWindowRgn(
HWND hWnd,
//
HRGN hRgn,
//
BOOL bRedraw
//
);
113
,
.
.
hRgn,
,
.
SelectClipRgn:
SelectClipRgn(hDC, hRgn);
GDI
. SelectClipRgn hRgn
.
,
SelectClipRgn NULL:
SelectClipRgn(hDC, NULL);
,
, .
,
,
, (. 12).
2.2
12.
1
(. 1.1). DrawText.
, , ,
, (. 2.19).
2.19. ,
SYSTEM_FONT
SelectObject
SetTextColor
SetBkColor
OPAQUE
SetBkMode
MM_TEXT
SetMapMode
,
GDI. ,
, SetTextColor. ,
114
2. GDI
SYSTEM_FONT ,
.
, ,
.
,
. (character set).
ASCII1. ASCII (. 2.22)
7 ,
27 = 128 .
. 2.22. ASCII
. 2.22
.
.
. , N 0x4E,
01001110 78.
32 ( 0x00 0x1F)
. ( 0x0D)2,
( 0x0A) 3.
( 0x20), ,
, .
( 0x7F) .
ASCII
8 , 256 .
128 ASCII.
IBM, IBM PC
80 .
,
. IBM
1
, , Enter.
Windows .
115
, , BIOS.
,
Microsoft Windows, ,
, 0xB0
0xDF.
IBM,
(code pages). ,
, CP437 (code page 437).
. CP866 CP437 ,
,
. CP866
. 2.23.
. 2.23. CP866
Microsoft Windows
ASCII,
MSDOS,
. ANSI1, , ,
ISO2.
ANSI ,
,
. . 2.20.
. 2.24 Windows Latin1 (
1252), . 2.25 Windows Cyrillic (
1251).
, ,
1
116
2. GDI
, .
. ,
932 ( ), 949 ( ) 950 (
) .
2.20. ANSI
0 .. 127
128 .. 255
ASCII
ASCII
ASCII
1253
ASCII
1254
ASCII
...
...
...
117
Win API,
,
EnumSystemCodePages.
Regional Settings ( )
Windows.
Unicode
, ,
, ,
.
Unicode. Unicode,
, Apple, HewlettPackard, IBM, Microsoft, Sun
. ,
65 536 . Unicode
.
Unicode . ,
0x0000 0x007F,
ASCII. 29 902
, , .
Windows ANSI
, Unicode. Win32 API,
, ANSI Unicode.
, ANSI, Unicode.
#define UNICODE,
Unicode, ANSI. ,
.
:
char TCHAR,
char* LPTSTR, const char* LPCTSTR.
TEXT,
"abcd" TEXT("abcd").
C, ,
.
, #define UNICODE,
, :
#ifdef UNICODE
#define sprintf swprintf
#define sscanf swscanf
#define strcpy wcscpy
#define strcat wcscat
#define strlen wcslen
#endif
ANSI,
.
118
2. GDI
, Windows,
:
(typeface) ,
.
Arial, Times New Roman, Courier New.
,
.
. Windows
(normal) , (italic), (bold),
(underline), (strike out).
, .
.
. .
. i
, m.
.
(glyph)
.
.
. 2.26 , ,
.
. 2.26.
(
Windows)
Don't care
FF_DONTCARE
0x00
( )
Roman
FF_ROMAN
0x10
(), Times New Roman
Swiss
FF_SWISS
0x20
,
Arial
Modern
FF_MODERN
0x30
, Courier New
119
(
Windows)
Script
FF_SCRIPT
0x40
, Monotype
Corsiva
Decorative
FF_DECORATIVE
0x50
, Old English
Windows : GDI
(device fonts). GDI ,
.
. ,
.
GDI :
;
TrueType.
.
. ,
. , ,
.
,
, , ,
.
Windows.
, .
.
, ,
,
.
. , ,
.fon.
TrueType Windows 3.1
. TrueType
, Apple Computer Inc. Microsoft
Corporation.
. TrueType ,
. , Windows
, .
.
TrueType ,
, WYSIWYG (WhatYou
SeeIsWhatYouGet)1.
120
2. GDI
TrueType
, Windows .
.
,
, ,
,
.
.
TrueType .ttf.
Windows OpenType.
PostScript,
TrueType. OpenType .otf.
OpenType OpenType .
, TrueType,
.ttc.
,
, (system
font table),
. ,
,
EnumFontFamilies ChooseFont.
: AddFontResource
AddFontResourceEx.
. ,
.
,
Windows.
,
RemoveFontResource.
, ,
WM_FONTCHANGE.
, ,
.
[6].
.
, ,
.
(font embedding)
.
,
.
121
. TrueType/
OpenType GetOutlineTextMetrics
otmfsType OUTLINETEXTMETRIC.
Win32 GDI ,
. 2.27.
. 2.27.
.
.
.
tmHeight
.
tmAscent
.
tmDescent
.
tmInternalLeading
, .
tmExternalLeading
.
. 0,01389
(1/71,99424). 1/72 .
.
, ,
GetTextMetrics:
TEXTMETRIC
lptm. TEXTMETRIC :
typedef
LONG
LONG
LONG
LONG
struct tagTEXTMETRIC
tmHeight;
tmAscent;
tmDescent;
tmInternalLeading;
{
//
//
//
//
122
2. GDI
LONG
LONG
LONG
LONG
LONG
tmExternalLeading;
tmAveCharWidth;
tmMaxCharWidth;
tmWeight;
tmOverhang;
//
//
//
// ()
//
//
LONG tmDigitizedAspectX; //
LONG tmDigitizedAspectY; //
TCHAR tmFirstChar;
// ,
//
TCHAR tmLastChar;
// ,
TCHAR tmDefaultChar;
// ,
TCHAR tmBreakChar;
//
//
BYTE tmItalic;
//
BYTE tmUnderlined;
//
BYTE tmStruckOut;
//
BYTE tmPitchAndFamily;
// ,
BYTE tmCharSet;
//
} TEXTMETRIC;
(. . 2.27) , ,
.
tmWeight () .
0 1000, 400
, 700 .
tmOverhang ,
,
, . TrueType
, .
tmDigitizedAspectX tmDigitizedAspectY MSDN
(horizontal aspect of the device)
(vertical aspect of the device) ,
. , ,
GetDeviceCaps LOGPIXELSX LOGPIXELSY,
1
1 .
, tmDigitizedAspectY /
tmDigitizedAspectX, (aspect ratio).
tmDefaultChar .
, ,
, tmDefaultChar.
. 2.222.25 , Windows
.
tmBreakChar (0x20).
tmPitchAndFamily ,
. .
. 2.22.
.
Windows . 2.21.
123
2.22.
TMPF_FIXED_PITCH
0x01
, ,
. ,
TMPF_VECTOR
0x02
TMPF_TRUETYPE
0x04
, True Type
TMPF_DEVICE
0x08
tmCharSet .
, wingdi.h.
. 2.23.
2.23.
ANSI_CHARSET
DEFAULT_CHARSET
SYMBOL_CHARSET
SHIFTJIS_CHARSET
128
HANGUL_CHARSET
129
GB2312_CHARSET
134
CHINESEBIG5_CHARSET
136
GREEK_CHARSET
161
Windows NT/2000
TURKISH_CHARSET
162
Windows NT/2000
HEBREW_CHARSET
177
Windows NT/2000
ARABIC_CHARSET
178
Windows NT/2000
RUSSIAN_CHARSET
204
Windows NT/2000
EASTEUROPE_CHARSET
238
Windows NT/2000
OEM_CHARSET
255
GetTextMetrics,
TEXTMETRIC, :
TEXTMETRIC tm ;
GetTextMetrics:
hDC = GetDC(hWnd) ;
GetTextMetrics(hDC, &tm) ;
tm. :
ReleaseDC(hWnd, hDC) ;
. , 96 dpi1,
: ) Arial,
18 ; ) MM_TEXT,
, .
1
124
2. GDI
GetTextMetrics tm
:
{18, 15, 3, 2, 1, 7, 43, 400, 0, 96, 96, 30, 255, 31, 32, 0, 0, 0, 39, 204}
, tmPitchAndFamily
, 39
0x27.
,
.
,
. .
GDI,
. GDI
, .
GDI
.
, HFONT.
SYSTEM_FONT,
,
. ,
, ,
ANSI.
OEM1.
() GetStockObject,
, . 2.24.
2.24.
OEM_FIXED_FONT
ANSI_FIXED_FONT
ANSI_VAR_FONT
SYSTEM_FONT
10
11
12
13
DEVICE_DEFAULT_FONT
14
SYSTEM_FIXED_FONT
16
DEFAULT_GUI_FONT
17
OEM
ANSI
ANSI
ANSI
, , , ,
,
ANSI .
(
Windows 3.0)
, (
Windows NT/2000)
125
,
SelectObject.
.
.
. GDI
CreateFont, CreateFontIndirect CreateFontIndirectEx.
CreateFontIndirectEx,
OpenType
Microsoft. MSDN.
CreateFont 14
, .
CreateFontIndirect.
LOGFONT, 14 .
:
HFONT CreateFontIndirect(CONST LOGFONT* lplf);
LOGFONT wingdi.h :
typedef struct tagLOGFONT
{
int lfHeight;
int lfWidth;
int lfEscapement;
int lfOrientation;
int lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
char lfFaceName[LF_FACESIZE];
} LOGFONT;
:
lfHeight .
, .
, tmHeight . 2.27.
, 12 (
).
, tmHeight tmInternalLeading.
lfWidth .
lfWidth ,
.
lfEscapement X
. .
126
2. GDI
lfOrientation X
. .
(GM_ADVANCED),
Windows NT/2000, lfEscapement
lfOrientation .
(GM_COMPATIBLE) lfEscapement ,
. MSDN
lfEscapement lfOrientation.
lfWeight () 0 1000.
, 400 , 700 .
. 2.25 ,
. FW_DONTCARE
.
2.25. 1
FW_DONTCARE
FW_THIN
100
FW_EXTRALIGHT
200
FW_ULTRALIGHT
200
FW_LIGHT
300
FW_NORMAL
400
FW_REGULAR
400
FW_MEDIUM
500
FW_SEMIBOLD
600
FW_DEMIBOLD
600
FW_BOLD
700
FW_EXTRABOLD
800
FW_ULTRABOLD
800
FW_HEAVY
900
FW_BLACK
900
lfItalic , TRUE.
lfUnderline .
lfStrikeOut .
lfCharSet . ,
. 2.23.
lfOutPrecision
. GDI
.
. 2.26.
, ,
FW_NORMAL, FW_REGULAR FW_BOLD.
127
2.26. lfOutPrecision
OUT_DEFAULT_PRECIS
OUT_TT_PRECIS
OUT_DEVICE_PRECIS
OUT_RASTER_PRECIS
OUT_TT_ONLY_PRECIS
OUT_OUTLINE_PRECIS
0
4
5
6
7
8
True Type
True Type
True Type
lfClipPrecision ,
. . 2.27,
. ,
, CLIP_DEFAULT_PRECIS.
2.27. lfClipPrecision
CLIP_DEFAULT_PRECIS
CLIP_LH_ANGLES
0
0x10
CLIP_EMBEDDED
0x80
,
( ).
,
,
,
lfQuality . ,
. 2.28. TrueType DRAFT_QUALITY
PROOF_QUALITY ,
.
2.28. lfQuality
DEFAULT_QUALITY
DRAFT_QUALITY
0
1
PROOF_QUALITY
NONANTIALIASED_QUALITY
ANTIALIASED_QUALITY
3
4
.
GDI ,
,
(antialiasing)
(antialiasing),
lfPitchAndFamily .
( ) ,
. 2.29, , . 2.21.
128
2. GDI
2.29. ,
DEFAULT_PITCH
0x0
FIXED_PITCH
0x1
VARIABLE_PITCH
0x2
fFaceName ,
. , ,
32 . ,
, EnumFontFamiliesEx.
fFaceName , GDI
, .
CreateFontIndirect
HFONT :
HFONT hFont;
LOGFONT:
LOGFONT lf;
,
. 0.
lf static:
static LOGFONT lf;
lf .
,
,
lf ChooseFont.
.
7 ( ).
lf , CreateFontIndirect:
hFont = CreateFontIndirect(&lf);
hFont
:
HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);
,
, ,
hFont:
DeleteObject(SelectObject(hDC, hOldFont));
2.3.
, CreateFont CreateFontIndirect,
,
SelectObject.
,
SelectObject, (font mapping).
129
. GDI
, LOGFONT, ,
, .
,
. ,
.
, lfCharSet.
,
. lfOutPrecision.
.
lfFaceName, lfPitchAndFamily.
,
.
GDI , lfHeight, lfWidth,
lfItalic, lfUnderline, lfStrikeOut.
,
.
GetTextMetrics, ,
.
, :
int GetTextFace(HDC hDC, int nCount, LPTSTR lpFaceName);
.
, LOGFONT.
lpFaceName. ( )
nCount.
, ,
. . GetTextFace
, NULL.
.
GetTextCharSet(HDC hDC)
, .
, GetFontLanguageInfo,
GetTextCharSetInfo GetOutlineTextMetrics.
, .
MSDN [6].
Win32 GDI
.
, ,
, , .
130
2. GDI
, ,
,
.
.
TextOut
:
BOOL TextOut (
HDC hdc,
int nXStart,
int nYStart,
LPCTSTR lpString,
int cbString
);
//
//
//
//
//
x-
y-
lpString,
.
,
, .
lpString
, cbString.
.
.
, . ,
(reference point): (nXStart, nYStart)
. ,
( )
: .
SetTextAlign:
UINT SetTextAlign(HDC hdc, UINT fMode);
, 1
, . 2.30.
. 0x00
.
2.30.
TA_NOUPDATECP
0x00
(nXStart, nYStart).
TA_UPDATECP
0x01
131
TA_LEFT
0x00
TA_RIGHT
0x02
TA_CENTER
0x06
TA_TOP
0x00
TA_BOTTOM
0x08
TA_BASELINE
0x18
TA_RTLREADING
0x100
( )
TextOut 2.1,
.
, TextOut ,
\n \t. ,
( SYSTEM_FONT)
.
,
. Windows
TabbedTextOut GetTabbedTextExtent.
TabbedTextOut :
LONG TabbedTextOut(HDC hDC, int X, int Y, LPCTSTR lpString, int nCount,
int iNumTabs, CONST LPINT lpnTabStops, int xTabOrigin);
, TextOut.
, iNumTabs, .
, lpnTabStops, ,
.
.
NULL,
,
. ,
lpnTabStops ,
.
, xTabOrigin,
. ,
,
lpnTabStops .
\t, GDI
, . GDI
,
132
2. GDI
(
), . GDI
. .
. ,
, n
n .
lpnTabStops .
GDI ,
,
.
TabbedTextOut 32
, ,
. .
GetTabbedTextExtent ,
.
TabbedTextOut. , ,
:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
int tabstop[] = { -130, 150, 250 };
int i;
const char* lines[] = {
"Group""\t" "Result" "\t" "Function"
"\t" "Parameters",
"Font" "\t" "HFONT"
"\t" "CreateFont" "\t" "(int nHeight, ...)",
"Text" "\t" "COLORREF""\t" "SetTextColor""\t" "(HDC hdc, ...)",
"Text" "\t" "BOOL"
"\t" "TextOut"
"\t" "(HDC hdc, ...)"
};
int x = 50, y = 50;
switch (uMsg)
{
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
for (i = 0; i < 4; i++) {
if (i == 1) y += 10;
y += HIWORD(TabbedTextOut(hDC, x, y, lines[i], strlen(lines[i]),
sizeof(tabstop)/sizeof(int), tabstop, x));
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
133
for. , ,
TabbedTextOut, ,
y .
x,
. , , GDI
, tabstop, x.
.2.28.
, ,
, MoveToEx, LineTo
TextOut. ,
.
180, 50 + 130.
. 2.28.
,
, (extra space).
, ,
GDI . .
SetTextCharacterExtra
, . GetTextCharacterExtra
.
,
. ,
SetTextCharacterExtra,
. for :
SetTextCharacterExtra(hDC, 4);
for (i = 0; i < 4; i++) {
if (i == 1) {
y += 10;
SetTextCharacterExtra(hDC, 0);
}
y += HIWORD(TabbedTextOut(hDC, x, y, lines[i], strlen(lines[i]),
sizeof(tabstop)/sizeof(int), tabstop, x));
}
,
.
(1)
TextOut ,
.
1
,
.
134
2. GDI
. (
). ,
, .
,
.
GDI
GetTextExtentPoint32 SetTextJustification.
,
x x + width. ,
width .
:
1.
SIZE size;
GetTextExtentPoint32(hDC, lpString, nCount, &size);
lpString,
nCount .
size. size.cx
, size.cy .
2. nBreak lpString.
,
. ,
, GetTextMetrics
tmBreakChar TEXTMETRIC.
3. ,
nBreak :
int breakExtra = width - size.cx;
4.
SetTextJustification(hdc, breakExtra, nBreak);
2.1 ,
.
135
2.1. TextJust
//////////////////////////////////////////////////////////////////////
// TextJust.cpp
#include <windows.h>
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL TextJustOut(HDC hdc, int x, int y, LPCTSTR lpStr, int width,
char breakChar = ' ');
//////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("Text Justification", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
char* text[6] =
{ "",
" ",
"
"
"
"
};
",
, ",
, ",
, ."
136
2. GDI
2.1 ()
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
BOOL TextJustOut(HDC hdc, int x, int y, LPCTSTR lpStr, int width,
TCHAR breakChar)
{
SIZE size;
int nCount = strlen(lpStr);
SetTextJustification(hdc, 0, 0);
GetTextExtentPoint32(hdc, lpStr, nCount, &size);
int nBreak = 0;
for (int i = 0; i < nCount; ++i)
if (lpStr[i] == breakChar)
nBreak++;
int breakExtra = width - size.cx;
if (breakExtra < 0) breakExtra = 0;
SetTextJustification(hdc, breakExtra, nBreak);
return TextOut(hdc, x, y, lpStr, nCount);
}
//////////////////////////////////////////////////////////////////////
KWnd,
KWnd.h KWnd.cpp, 1.2,
Project Workspace .
, ,
TextJustOut. TextJustOut ,
text. nWidth
text[5]. . 2.29.
. 2.29.
Windows
, . , ,
.
Win32 GDI DrawText DrawTextEx.
137
DrawText :
int DrawText(
HDC hDC,
LPCTSTR lpString,
int nCount,
LPRECT lpRect,
UINT uFormat
);
//
//
//
//
//
, DrawText
.
. 1 nCount,
.
, nCount.
DrawText ,
lpRect. , uFormat,
. ,
.
. 2.31 ( . MSDN).
2.31. DrawText
DT_LEFT
DT_CENTER
DT_RIGHT
DT_TOP
DT_VCENTER
0x0000
0x0001
0x0002
0x0000
0x0004
DT_BOTTOM
0x0008
DT_WORDBREAK
0x0010
DT_SINGLELINE
0x0020
DT_EXPANDTABS
0x0040
DT_NOPREFIX
0x0800
DT_PATH_ELLIPSIS
0x4000
DT_END_ELLIPSIS
0x8000
(
DT_SINGLELINE)
(
DT_SINGLELINE)
, . ,
DT_SINGLELINE
.
( )
\t , .
&. DrawText &
, && &. DT_NOPREFIX
& ,
,
( DT_SINGLELINE)
,
( DT_SINGLELINE)
138
2. GDI
uFormat , Windows
, (\r 0x0D)
(\n 0x0A). ,
.
.
, .
, ,
, .
, DT_WORDBREAK.
, DT_ SINGLELINE.
.
DrawText
.
.
DT_VCENTER DT_BOTTOM.
.
, .
DrawText. . 2.30
DrawText(hDC, text1, -1, &rect, uFormat);
char text1[] = "&Open C:\\WINNT\\system32\\gdi32.dll";
uFormat:
) 0;
) DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX;
) DT_SINGLELINE | DT_RIGHT | DT_BOTTOM.
rect
Rectangle.
. 2.31
, .
uFormat:
) 0;
) DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS;
) DT_SINGLELINE | DT_BOTTOM | DT_PATH_ELLIPSIS.
, DrawText
, ,
,
.
139
. 2.32
DrawText(hDC, text2, -1, &rect, DT_SINGLELINE | DT_VCENTER | DT_EXPANDTABS);
char text2[] = "&Open \tC:\\WINNT\\system32\\gdi32.dll";
\t.
. 2.31. text1 ,
. 2.32. text2,
. 2.33
char text3[] = "Warning: this computer program \n is protected by copyright law \n and
international treaties";
DrawText(hDC, text3, -1, &rect, DT_CENTER);
, ,
char text4[] = "Warning: this computer program is protected by copyright law and
international treaties";
DrawText(hDC, text4, -1, &rect, DT_WORDBREAK);
, . 2.34.
. 2.34.
DT_WORDBREAK
DrawTextEx :
int DrawTextEx(HDC hDC, LPTSTR lpchTExt, int cchText, LPRECT lpRect,
UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams);
DrawText ,
DRAWTEXTPARAMS.
, ,
140
2. GDI
.
MSDN.
ExtTextOut
ExtTextOut, TextOut,
:
BOOL ExtTextOut(HDC hdc, int X, int Y, UINT fuOptions, CONST RECT* lprc,
LPCTSTR lpString, UINT cbCount, CONST INT* lpDx);
TextOut(hDC, x, y, lpString, cbCount);
. fuOptions
, .
1 lprc ,
, ,
. lpDx
. . 2.32
, ,
fuOptions.
2.32. ExtTextOut
ETO_OPAQUE
0x0002
ETO_CLIPPED
ETO_GLYPH_INDEX
0x0004
0x0010
ETO_RTLREADING
0x0080
ETO_NUMERICSLOCAL
ETO_NUMERICSLATIN
ETO_IGNORELANGUAGE
ETO_PDY
0x0400
0x0800
0x1000
0x2000
lprc
lprc
lpString
( ),
GetCharacterPlacement.
16-
lpDx ,
,
ExtTextOut
.
, ,
ExtTextOut
ETO_OPAQUE ETO_CLIPPED.
1
NULL.
141
ETO_GLYPH_INDEX.
, WYSIWYG.
,
.
ExtTextOut [6].
.
:
( ).
GDI .
,
. [6].
,
. ,
, ,
. (scroll bars)
.
.
:
;
Scroll bar.
7.
,
, , . 2.35.
, CreateWindow
WS_VSCROLL ( ) WS_HSCROLL (
) dwStyle.
, .
.
, ,
.
.
.
(thumb).
.
.
142
2. GDI
. 2.35.
, , ,
, .
Windows .
.
,
(
4).
:
(range), ,
(nMin) (nMax)
.
, 1
. range range = nMax nMin + 1.
(position) ,
.
,
.
.
(page) ,
,
. Windows
.
, .
, ,
1 .
143
.
,
.
0 100.
. ,
nLine ,
. nMin = 0 nMax =
= nLine 1. nMin = 1 nMax = nLine.
,
, .
,
SetScrollInfo:
hwnd ,
, Scroll
Bar. fnBar.
fnBar .
SB_VERT ( ), SB_HORZ (
) SB_CTL ( Scroll Bar). lpsi
SCROLLINFO, .
bRedraw ,
SetScrollInfo.
SCROLLINFO winuser.h :
typedef struct tagSCROLLINFO
{
UINT cbSize;
//
UINT fMask;
// /
int nMin;
//
int nMax;
//
UINT nPage;
//
int nPos;
//
int nTrackPos;
// ,
} SCROLLINFO;
fMask ,
SetScrollInfo GetScrollInfo.
, . 2.33.
GetScrollInfo.
, ,
Windows
. , Windows :
;
;
,
;
144
2. GDI
,
.
2.33. fMask
SIF_PAGE
nPage
nPos ,
nMin nMax
nTrackPos , (
GetScrollInfo)
SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS
. ,
SIF_POS
SIF_RANGE
SIF_TRACKPOS
SIF_ALL
SIF_DISABLENOSCROLL
:
;
Windows WM_VSCROLL
WM_HSCROLL,
.
, wParam
, ,
.
, SB_.
. 2.36 , Windows
.
. ,
.
SB_LINEUP SB_PAGEUP,
.
SB_ENDSCROLL , . ,
SB_ENDSCROLL .
(thumb)
SB_THUMBTRACK. wParam
SB_THUMBTRACK SB_THUMBPOSITION, wParam
.
wParam .
lParam, ,
.
145
. 2.36. wParam
,
. : yInc
xInc .
. , .
ScrollWindow:
BOOL ScrollWindow(
HWND hWnd,
int XAmount,
int YAmount,
CONST RECT* lpRect,
CONST RECT* lpClipRect
);
//
//
//
//
//
XAmount YAmount .
lpRect lpClipRect NULL,
.
, WM_VSCROLL
:
ScrollWindow(hWnd, 0, -yStep * yInc, NULL, NULL);
WM_HSCROLL :
ScrollWindow(hWnd, -cxChar * xInc, 0, NULL, NULL);
yStep ,
cxChar .
,
.
. ,
:
si.nPos += yInc;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
si SCROLLINFO.
146
2. GDI
, ScrollWindow
.
,
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
, UpdateWindow WM_PAINT
. ,
,
( SB_THUMBTRACK). ,
InvalidateRect
WM_PAINT ,
.
, WM_PAINT
,
.
2.2.
TextViewer
. : ,
TextOut TabbedTextOut,
.
,
, .
KDocument , ,
.
KDocument.h,
KDocument.cpp.
,
2.21.
2.2. TextViewer
//////////////////////////////////////////////////////////////////////
// KDocument.h
#include <windows.h>
#include <vector>
#include <string>
using namespace std;
class KDocument {
1
public:
BOOL
void
void
void
void
void
147
int cxChar;
//
int yStep;
// ()
int lineLenMax;
//
SCROLLINFO vsi;
//
int vertRange;
//
SCROLLINFO hsi;
//
int horzRange;
//
private:
vector<string> lines; //
};
//////////////////////////////////////////////////////////////////////
// KDocument.cpp
#include <windows.h>
#include <fstream>
#include "KDocument.h"
BOOL KDocument::Open(const char* file) {
ifstream finp(file);
char buf[200];
if(!finp.good()) {
MessageBox(NULL, " ", "Error", MB_OK);
return FALSE;
}
// , lines
while(!finp.eof()) {
finp.getline(buf, 199);
buf[199] = 0;
lines.push_back(string(buf));
}
//
lineLenMax = 0;
for (int i = 0; i < lines.size(); ++i) {
int lineLen = lines[i].size();
// ,
int iTabPos = 0;
while (1) {
iTabPos = lines[i].find('\t', iTabPos);
if (iTabPos != -1) {
lineLen += 8;
iTabPos++;
}
else break;
}
if (lineLen > lineLenMax) lineLenMax = lineLen;
}
return TRUE;
}
void KDocument::Initialize(LPTEXTMETRIC tm) {
148
2. GDI
2.2 ()
cxChar = tm->tmAveCharWidth;
yStep = tm->tmHeight + tm->tmExternalLeading;
vsi.nMin = vsi.nPos = 0;
hsi.nMin = hsi.nPos = 0;
}
void KDocument::ScrollSettings(HWND hwnd, int width, int height) {
//
vsi.cbSize = sizeof(vsi);
vsi.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
vsi.nPage = height / yStep - 1;
vsi.nMax = lines.size() - 1;
if (vsi.nPage > vsi.nMax)
vsi.nPos = vsi.nMin;
vertRange = vsi.nMax - vsi.nMin + 1;
SetScrollInfo(hwnd, SB_VERT, &vsi, TRUE);
//
hsi.cbSize = sizeof(SCROLLINFO);
hsi.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
hsi.nPage = width/cxChar - 2;
hsi.nMax = lineLenMax;
if (hsi.nPage > hsi.nMax)
hsi.nPos = hsi.nMin;
horzRange = hsi.nMax - hsi.nMin + 1;
SetScrollInfo(hwnd, SB_HORZ, &hsi, TRUE);
}
void KDocument::UpdateVscroll(HWND hwnd, int yInc) {
//
yInc = min(yInc, vertRange - (int)vsi.nPage - vsi.nPos);
//
yInc = max(yInc, vsi.nMin - vsi.nPos);
if (yInc) {
ScrollWindow(hwnd, 0, -yStep * yInc, NULL, NULL);
vsi.nPos += yInc;
SetScrollInfo(hwnd, SB_VERT, &vsi, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow (hwnd);
}
}
void KDocument::UpdateHscroll(HWND hwnd, int xInc) {
//
xInc = min(xInc, horzRange - (int)hsi.nPage - hsi.nPos);
//
xInc = max(xInc, hsi.nMin - hsi.nPos);
if (xInc) {
ScrollWindow(hwnd, -cxChar * xInc, 0, NULL, NULL);
hsi.nPos += xInc;
SetScrollInfo(hwnd, SB_HORZ, &hsi, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow (hwnd);
}
149
}
void KDocument::PutText(HWND hwnd, HDC hdc) {
RECT rect;
GetClientRect(hwnd, &rect);
rect.left += cxChar;
rect.right -= cxChar;
HRGN hRgn = CreateRectRgnIndirect(&rect);
SelectClipRgn(hdc, hRgn);
int x = cxChar * (hsi.nMin - hsi.nPos + 1);
int y = yStep;
int amountLines = lines.size();
int iBeg = vsi.nPos;
int iEnd = (vsi.nPos+vsi.nPage < amountLines)? vsi.nPos+vsi.nPage :
amountLines;
for (int i = iBeg; i < iEnd; ++i) {
int iTabPos = lines[i].find('\t');
if (-1 == iTabPos)
TextOut(hdc, x, y, lines[i].c_str(), lines[i].size());
else
TabbedTextOut(hdc, x, y, lines[i].c_str(), lines[i].size(), 0, 0, x);
y += yStep;
}
SelectClipRgn(hdc, NULL);
}
//////////////////////////////////////////////////////////////////////
// TextViewer.cpp
#include <windows.h>
#include "KWnd.h"
#include "KDocument.h"
#define FILE_NAME "D:\\Program files\\Microsoft Visual
Studio\\VC98\\MFC\\SRC\\README.TXT"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
KDocument doc;
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
if (!doc.Open(FILE_NAME)) return 0;
KWnd mainWnd("Text Viewer", hInstance, nCmdShow, WndProc, NULL,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, CS_HREDRAW | CS_VREDRAW,
WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
150
2. GDI
2.2 ()
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
TEXTMETRIC tm;
int cxClient=0, cyClient=0;
static int xInc, yInc;
switch (uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
GetTextMetrics(hDC, &tm);
doc.Initialize(&tm);
ReleaseDC(hWnd, hDC);
break;
case WM_SIZE:
hDC = GetDC(hWnd);
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
if (cxClient > 0)
doc.ScrollSettings(hWnd, cxClient, cyClient);
ReleaseDC(hWnd, hDC);
break;
case WM_VSCROLL:
switch(LOWORD(wParam)) {
case SB_LINEUP:
yInc = -1; break;
case SB_LINEDOWN:
yInc = 1; break;
case SB_PAGEUP:
yInc = -(int)doc.vsi.nPage; break;
case SB_PAGEDOWN:
yInc = (int)doc.vsi.nPage; break;
case SB_THUMBTRACK:
yInc = HIWORD(wParam) - doc.vsi.nPos; break;
default: yInc = 0;
}
doc.UpdateVscroll(hWnd, yInc);
break;
case WM_HSCROLL:
switch(LOWORD(wParam)) {
case SB_LINELEFT:
xInc = -1; break;
case SB_LINERIGHT:
xInc = 1; break;
case SB_PAGELEFT:
xInc = -0.8 * (int)doc.hsi.nPage; break;
case SB_PAGERIGHT:
xInc = 0.8 * (int)doc.hsi.nPage; break;
case SB_THUMBTRACK:
xInc = HIWORD(wParam) - doc.hsi.nPos; break;
default: xInc = 0;
}
151
doc.UpdateHscroll(hWnd, xInc);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
doc.PutText(hWnd, hDC);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
KDocument:
lines,
string.
Open . ,
\n.
lines. for
lineLenMax .
lines[i] find
string, \t
1, . ScrollSettings
lineLenMax
.
Initialize .
cxChar ,
yStep .
, tm.
ScrollSettings
width height
.
UpdateVscroll
.
ScrollWindow,
SetScrollInfo
UpdateWindow.
.
.
.
152
2. GDI
,
vertRange (int)vsi.nPage.
. ,
int vsi.nPage
min.
, vsi.nMin.
UpdateHscroll
.
UpdateVscroll.
PutText
.
(
) hRgn.
CreateRectRgnIndirect,
rect,
,
cxChar.
SelectClipRgn.
for
vsi.nPos
hsi.nPos . lines[i]
, TextOut.
TabbedTextOut.
MM_TEXT,
.
y
yStep.
hsi.nPos hsi.nMin, x,
cxChar (hsi.nMin hsi.nPo s + 1), cxChar.
, .
hRgn,
, x = cxChar.
hsi.nPo s > 0 x ,
,
.
, .
, , Windows,
, .
, , .
SelectClipRgn(hdc, NULL)
.
153
, TextViewer.cpp:
doc KDocument.
WS_VSCROLL | WS_HSCROLL,
KWnd windowStyle.
.
WM_PAINT
doc.PutText(hWnd, hDC).
.
U_T_Diagram
, , ,
, .
.
220 , 50 .
, .
. 2.37 U_T_Diagram .
,
. ,
,
. ,
,
.
T f
T = 1/f, 50 0,02 , 20 .
, U
Um U = 0,707 . Um.
, 311,17 .
1
154
2. GDI
. 2.37. U_T_Diagram
, .
1 , X Y 3 , 5
.
,
.
,
, ,
.
(viewport)
, GetClientRect.
.
, (window).
, ,
, ,
. ,
. , ,
. . ,
,
mx my1. .
Win32 API . ,
CreatePen(penStyle, nWidth, crColor) nWidth
. nWidth,
1
155
1
.
,
xVE = 952, yVE = 7021,
xWE = 60 (), yWE = 1000 (),
mx = 952 / 60 = 15,86 , , 16 .
my = 702 / 1000 = 0,72 , ,
.
, . 2.37,
.
MM_ISOTROPIC,
.
.
,
:
nPixPerVolt = yVE / 1000.0;
nPixPerMs = xVE / 60.0;
2.3.
2.3. U_T_Diagram2
//////////////////////////////////////////////////////////////////////
// U_T_Diagram.cpp
#include <windows.h>
#include <math.h>
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawDiagram(HWND, HDC);
#define Pi 3.14159265
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd(" ",
hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
,
.
156
2. GDI
2.3 ()
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
switch (uMsg)
{
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
DrawDiagram(hWnd, hDC);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
void DrawDiagram(HWND hwnd, HDC hdc)
{
RECT rect;
GetClientRect(hwnd, &rect);
const int xVE = rect.right - rect.left;
const int yVE = rect.bottom - rect.top;
const int xWE = xVE;
const int yWE = yVE;
double nPixPerVolt = yVE / 1000.0;
double nPixPerMs = xVE / 60.0;
// n Pixels Per Millisec
SetMapMode (hdc, MM_ISOTROPIC);
SetWindowExtEx (hdc, xWE, yWE, NULL);
SetViewportExtEx (hdc, xVE, -yVE, NULL);
SetViewportOrgEx (hdc, 10*nPixPerMs, yVE/2, NULL);
const int
const int
const int
const int
const int
const int
int x, y;
tMin = 0;
tMax = 40;
uMin = -400;
uMax = 400;
tGridStep = 5;
uGridStep = 100;
//
//
//
//
ms
ms
V
V
char* xMark[] = { "0", "5", "10", "15", "20", "25", "30", "35", "40"};
char* yMark[] = { "-400","-300","-200","-100", "0", "100", "200", "300",
"400"};
//
HPEN hPen0 = CreatePen(PS_SOLID, 1, RGB(0, 160, 0));
HPEN hOldPen = (HPEN)SelectObject(hdc, hPen0);
int u = uMin;
157
t = tMin;
yMin = uMin * nPixPerVolt;
yMax = uMax * nPixPerVolt;
(i = 0; i < 9; ++i) {
x = t * nPixPerMs;
MoveToEx(hdc, x, yMin, NULL);
LineTo(hdc, x, yMax);
TextOut(hdc, x-6, yMin-10, xMark[i], strlen(xMark[i]));
t += tGridStep;
}
// "x"
HPEN hPen1 = CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
SelectObject(hdc, hPen1);
MoveToEx(hdc, 0, 0, NULL); LineTo(hdc, xMax, 0);
static LOGFONT lf;
lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
lf.lfItalic = TRUE;
lf.lfWeight = FW_BOLD;
lf.lfHeight = 20;
lf.lfCharSet = DEFAULT_CHARSET;
lstrcpy( (LPSTR)&lf.lfFaceName, "Arial" );
HFONT hFont0 = CreateFontIndirect(&lf);
HFONT hOldFont = (HFONT)SelectObject(hdc, hFont0);
SetTextColor(hdc, RGB(0, 0, 200));
TextOut(hdc, xMax+10, 10, "t (ms)", 6);
// "y"
MoveToEx(hdc, 0, yMin, NULL); LineTo(hdc, 0, yMax);
TextOut(hdc, -10, yMax+30, "u (V)", 5);
//
HPEN hPen2 = CreatePen(PS_SOLID, 5, RGB(200, 0, 100));
SelectObject(hdc, hPen2);
int tStep = 1;
double radianPerMs = 2 * Pi / 20;
const double uAmplit = 311.17;
// volt
t = tMin;
MoveToEx(hdc, 0, 0, NULL);
while (t <= tMax) {
u = uAmplit * sin( t * radianPerMs);
LineTo(hdc, t * nPixPerMs, u * nPixPerVolt);
t += tStep;
}
//
char* title = " . ";
158
2. GDI
2.3 ()
lf.lfItalic = FALSE;
lf.lfWeight = FW_BOLD;
lf.lfHeight = 30;
HFONT hFont1 = CreateFontIndirect(&lf);
SelectObject(hdc, hFont1);
SetTextColor(hdc, RGB(0, 200, 0));
TextOut(hdc, 0, yMax + 70, title, strlen(title));
SelectObject(hdc, hOldPen);
SelectObject(hdc, hOldFont);
}
//////////////////////////////////////////////////////////////////////
DrawDiagram, WM_PAINT.
,
.
,
, .
1 ,
1 .
,
SetViewportExtEx (hdc, xVE, -yVE, NULL);
,
, .
:
SetViewportOrgEx (hdc, 10*nPixPerMs, yVE/2, NULL);
10 .
tMin, tMax, uMin, uMax,
tGridStep, uGridStep, .
t, u. (
)
nPixPerMs, nPixPerVolt.
while
sin(x).
, u.
LineTo ,
u.
sin ,
= 2 . . f = 2 . / T
:
radianPerMs = 2 * Pi / 20;
, , ,
.
159
GDI. ,
,
GDI. ,
, , , .
,
,
DIB DIB.
, 24
RGB1, . ,
, 256 .
, ,
.
, Windows ,
. ,
, GetDeviceCaps, RASTERCAPS,
, RC_PALETTE.
, ,
.
() ,
.
.
Win32 GDI .
(system palette) ,
.
1
160
3. GDI. , ,
, , .
. .
256 (), 20
,
. , ,
, .
(logical palette) .
.
,
.
CreatePalette CreateHalftonePalette
RealizePalette. Windows
.
, , Windows
, ,
(dithering) ,
.
, MSDN . ,
COLORREF,
PALETTERGB, RGB.
,
(default palette), 20 ,
. ,
, 20 .
,
, Windows 1
.
.
.
,
.
, ,
, Windows WM_QUERYNEWPALETTE.
, ,
.
WM_PALETTECHANGED ,
.
,
, .
, .
161
. , ,
, ,
, .
,
,
. ,
: .
.
COMBOBOX
.
, , , :
256 ;
Hi Color (16 );
typedef struct {
BYTE peRed;
BYTE peGreen;
BYTE peBlue;
BYTE peFlags;
} PALETTEENTRY;
PALETTEENTRY
RGB. peFlags .
.
GetSystemPaletteEntries, :
UINT
GetSystemPaletteEntries(
HDC hdc,
//
UINT iStartIndex,
//
UINT nEntries,
//
LPPALETTEENTRY lppe
// PALETTEENTRY
);
lppe ,
. NULL,
.
.
, , , ,
.
20
. . 3.1.
162
3. GDI. , ,
3.1.
RGB
0
1
2
3
4
5
6
7
8
9
246
247
248
249
250
251
252
253
254
-
-
-
-
-
-
-
-
-
-
255
True Color
True Color
True Color
True Color
. ,
,
. ,
XOR
.
.
, 255 (0xFF),
. 1
RGB(0x80, 0x00, 0x00). , 254 (0xFE),
. ,
RGB (RGB(0x7F, 0xFF, 0xFF)),
.
8 8 ,
. 8, 9, 246, 247 .
RGB True Color. 256
RGB .
, ,
, 3.1.
3.1. SystemPalette
//////////////////////////////////////////////////////////////////////
// SystemPalette.cpp
#include <windows.h>
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
163
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("System palette", hInstance, nCmdShow, WndProc, NULL, 0, 0,
524, 543);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT r0;
RECT rect;
HBRUSH brush;
int dW, dH, i, j;
int index = 0;
PALETTEENTRY pal[256];
switch (uMsg)
{
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
GetSystemPaletteEntries(hDC, 0, 256, pal);
GetClientRect(hWnd, &r0);
dW = (r0.right - 4) / 16;
dH = (r0.bottom - 4) / 16;
SetViewportOrgEx(hDC, 2, 2, NULL);
for (i = 0; i < 16; ++i)
for (j = 0; j < 16; ++j) {
SetRect(&rect, j*dW, i*dH, (j+1)*dW - 1, (i+1)*dH - 1);
brush = CreateSolidBrush(RGB(pal[index].peRed,
pal[index].peGreen, pal[index].peBlue));
FillRect(hDC, &rect, brush);
DeleteObject(brush);
index++;
}
EndPaint(hWnd, &ps);
break;
case WM_PALETTECHANGED:
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_DESTROY:
164
3. GDI. , ,
3.1. ()
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
WM_PAINT.
GetSystemPaletteEntries
pal.
GetClientRect
r0, RECT.
r0.left r0.top , r0.right
r0.bottom .
WinMain
516 516 . dW dH,
rect,
brush, 32.
WM_PALETTECHANGED
InvalidateRect, , ,
WM_PAINT .
1.
256 , ,
. 3.1. ,
, , ,
2.
. ,
. 236
RGB,
. , ,
, MS Paint.
, . ,
MS Paint
.
. ,
True Color3. System palette ,
. 3.2. , ,
. ,
RGB(0x00, 0x00, 0x00). , True Color
, .
,
(www.piter.com).
, .
165
. 3.1. 256-
166
3. GDI. , ,
, ,
COLORREF,
:
COLORREF PALETTEINDEX(WORD wPaletteIndex);
COLORREF PALETTERGB(BYTE bRed, BYTE bGreen, BYTE bBlue);
PALETTEINDEX 32
.
.
PALETTERGB, RGB, ,
.
. PALETTERGB
, RGB
,
. ,
RGB ,
COLORREF.
,
, ,
20 .
, 8 ( 3.2).
3.2. ColorsWithDefaultPal
//////////////////////////////////////////////////////////////////////
// ColorsWithDefaultPal.cpp
#include <windows.h>
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("Colors with default palette", hInstance, nCmdShow, WndProc,
NULL, 0, 0, 800, 200);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
167
RECT r0;
RECT rect[8];
int dW, dH, i;
static HBRUSH brush[8];
COLORREF rgbColor[8] = { RGB(128,0,0), RGB(192,0,0),RGB(255,0,0),
RGB(255,192,0), RGB(176,250,133), RGB(245,197,137),
RGB(255,128,128), RGB(255,128,255)};
switch (uMsg)
{
case WM_CREATE:
for (i = 0; i < 8; ++i)
brush[i] = CreateSolidBrush(rgbColor[i]);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &r0);
dW = r0.right / 8;
dH = r0.bottom;
for (i = 0; i < 8; ++i) {
SetRect(&rect[i], i*dW, 0, (i+1)*dW, dH);
FillRect(hDC, &rect[i], brush[i]);
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
for (i = 0; i < 8; ++i)
DeleteObject(brush[i]);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
True Color,
, . 3.3.
8 , rgbColor:
, , , , , ,
, .
168
3. GDI. , ,
,
RGB .
256
. . 3.4.
. 3.4. (256- )
, .
.
,
.
,
.
:
1. ( CreateHalftonePalette).
2. ( SelectPalette).
3. RealizePalette.
SelectPalette :
HPALETTE
SelectPalette(
HDC hdc,
//
HPALETTE hpal,
//
BOOL bForceBackground
// ( )
);
, (TRUE)
(FALSE) Realize
Palette. .
, RealizePalette
, .
, , .
RealizePalette
, , ,
.
3.3 , ,
, .
WM_QUERYNEWPALETTE WM_PALETTECHANGED.
169
3.3. ColorsWithHalftonePal
//////////////////////////////////////////////////////////////////////
// ColorsWithHalftonePal.cpp
#include <windows.h>
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("Colors with halftone palette", hInstance, nCmdShow,
WndProc, NULL, 0, 0, 800, 200);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT r0;
RECT rect[8];
int dW, dH, i;
COLORREF paletteColor[8] = { PALETTERGB(128,0,0), PALETTERGB(192,0,0),
PALETTERGB(255,0,0), PALETTERGB(255,192,0), PALETTERGB(176,250,133),
PALETTERGB(245,197,137), PALETTERGB(255,128,128),
PALETTERGB(255,128,255)};
static HBRUSH brush[8];
static HPALETTE hPal;
HPALETTE hOldPal;
switch (uMsg)
{
case WM_CREATE:
for (i = 0; i < 8; ++i)
brush[i] = CreateSolidBrush(paletteColor[i]);
hDC = GetDC(hWnd);
hPal = CreateHalftonePalette(hDC);
ReleaseDC(hWnd, hDC);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
hOldPal = SelectPalette(hDC, hPal, FALSE);
GetClientRect(hWnd, &r0);
dW = r0.right / 8;
dH = r0.bottom;
for (i = 0; i < 8; ++i) {
SetRect(&rect[i], i*dW, 0, (i+1)*dW, dH);
FillRect(hDC, &rect[i], brush[i]);
}
170
3. GDI. , ,
3.3 ()
SelectPalette(hDC, hOldPal, TRUE);
EndPaint(hWnd, &ps);
break;
case WM_QUERYNEWPALETTE:
hDC = GetDC(hWnd);
SelectPalette(hDC, hPal, FALSE);
if (RealizePalette(hDC))
InvalidateRect(hWnd, NULL, TRUE);
ReleaseDC(hWnd, hDC);
break;
case WM_PALETTECHANGED:
hDC = GetDC(hWnd);
SelectPalette(hDC, hPal, FALSE);
if (RealizePalette(hDC))
InvalidateRect(hWnd, NULL, TRUE);
ReleaseDC(hWnd, hDC);
break;
case WM_DESTROY:
DeleteObject(hPal);
for (i = 0; i < 8; ++i)
DeleteObject(brush[i]);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
:
hPal WM_CREATE,
WM_QUERYNEWPALETTE,
WM_PALETTECHANGED. RealizePalette
,
. , InvalidateRect.
WM_PAINT
, .
256
, ,
True Color (. . 3.3).
,
. ,
.
,
, , .
paletteColor :
171
, , ,
.
,
. CreatePalette:
HPALETTE
CreatePalette(CONST
LOGPALETTE*
lplgpl);
lplgpl LOGPALETTE,
:
typedef struct tagLOGPALETTE {
WORD
palVersion;
//
WORD
palNumEntries; //
PALETTEENTRY palPalEntry[1];
} LOGPALETTE;
Windows 3.0
0x300.
palPalEntry PALETTEENTRY,
.
PALETTEENTRY .
RGB
, peFlags ,
. peFlags . 3.2.
3.2. peFlags
, RGB
. ,
PC_NOCOLLAPSE
() .
PC_EXPLICIT
.
PALETTEENTRY .
PC_RESERVED
, .
-
. ,
, LOGPALETTE palPalEntry
, ,
.
LOGPALETTE,
LOGPALETTE. .
RealizePalette , .
3.4 ,
, 128 , 16
, .
172
3. GDI. , ,
3.4. LogicPalette
//////////////////////////////////////////////////////////////////////
// LogicPalette.cpp
#include <windows.h>
#include "KWnd.h"
#define PAL_NUM_ENTRIES
#define NUM_RECT 16
128
typedef struct {
LOGPALETTE lp;
PALETTEENTRY ape[PAL_NUM_ENTRIES - 1];
} LogPal;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("Colors with logic palette", hInstance, nCmdShow, WndProc,
NULL, 0, 0, 808, 200);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT r0;
RECT rect[NUM_RECT];
int dW, dH, i;
static LogPal pal;
LOGPALETTE* pLP = (LOGPALETTE*) &pal;
static COLORREF paletteColor[NUM_RECT];
static HBRUSH brush[NUM_RECT];
static HPALETTE hPal;
HPALETTE hOldPal;
BYTE green;
BYTE stepPal, stepBrush;
switch (uMsg)
{
case WM_CREATE:
//
pLP->palVersion = 0x300; // Windows
pLP->palNumEntries = PAL_NUM_ENTRIES; //
stepPal = 256 / PAL_NUM_ENTRIES;
173
green = 255;
for (i = 0; i < PAL_NUM_ENTRIES; i++) {
pLP->palPalEntry[i].peRed = 0;
pLP->palPalEntry[i].peGreen = green;
pLP->palPalEntry[i].peBlue = 0;
pLP->palPalEntry[i].peFlags = 0;
green -= stepPal;
}
hPal = CreatePalette (pLP);
//
stepBrush = 256 / NUM_RECT;
for (i = 0; i < NUM_RECT; ++i)
brush[i] = CreateSolidBrush(PALETTERGB(0, stepBrush * i, 0));
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
hOldPal = SelectPalette(hDC, hPal, FALSE);
GetClientRect(hWnd, &r0);
dW = r0.right / NUM_RECT;
dH = r0.bottom;
for (i = 0; i < NUM_RECT; ++i) {
SetRect(&rect[i], i*dW, 0, (i+1)*dW, dH);
FillRect(hDC, &rect[i], brush[i]);
}
SelectPalette(hDC, hOldPal, TRUE);
EndPaint(hWnd, &ps);
break;
case WM_QUERYNEWPALETTE:
hDC = GetDC(hWnd);
SelectPalette(hDC, hPal, FALSE);
if (RealizePalette(hDC))
InvalidateRect(hWnd, NULL, TRUE);
ReleaseDC(hWnd, hDC);
break;
case WM_PALETTECHANGED:
hDC = GetDC(hWnd);
SelectPalette(hDC, hPal, FALSE);
if (RealizePalette(hDC))
InvalidateRect(hWnd, NULL, TRUE);
ReleaseDC(hWnd, hDC);
break;
case WM_DESTROY:
DeleteObject(hPal);
for (i = 0; i < NUM_RECT; ++i)
DeleteObject(brush[i]);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
174
3. GDI. , ,
LogPal
, LOGPALETTE.
LOGPALETTE,
PALETTEENTRY, (PAL_NUM_ENTRIES 1) .
LogPal WndProc:
static
LogPal
pal;
,
LOGPALETTE, LOGPALETTE,
pal:
LOGPALETTE*
pLP
(LOGPALETTE*)
&pal;
236, 20
.
PAL_NUM_ENTRIES, 128,
, 16 .
WM_CREATE. pal,
pLP, palPalEntry
. CreatePalette.
WM_QUERYNEWPALETTE
WM_PALETTECHANGED. , WM_PAINT
SelectPalette.
, . 3.5.
. 3.5. (256- )
, 2, ,
,
, , .
.
(vector graphics).
,
, .
(bitmap graphics).
, , , ,
175
, , ,
Microsoft Paint Adobe Photoshop.
, , (bitmap)
.
, .
.
.
, , 2n,
n . , VGA
256 8 .
, 224 , 24
, RGB 8 .
Windows
, , DDB
(device dependent bitmap). DDB ,
. , 256
, 8 .
DDB ,
.
,
, .
Windows 3.0, ,
, DIB (device independent bitmap).
DIB
.
RGB,
. , DIB,
,
, .
(DDB)
Windows,
,
. (DIB), ,
,
Windows.
DIB,
DDB ,
Win32 GDI, DIB.
-
(DIB)
,
. , DIB, .bmp.
DIB
BMP.
176
3. GDI. , ,
BMP
BMP,
, . 3.3.
3.3. DIB- ( BMP)
BITMAPFILEHEADER bmfHeader;
14
BITMAPINFOHEADER bmiHeader;
40
BITMAPV4HEADER (108 )
BITMAPV5HEADER (124 )
RGBQUAD bmiColors[];
BYTE aBitmapBits[][];
BITMAPFILEHEADER,
bmfHeader, :
typedef struct tagBITMAPFILEHEADER {
WORD
bfType;
//
DWORD bfSize;
//
WORD
bfReserved1; // ( )
WORD
bfReserved2; // ( )
DWORD bfOffbits;
//
} BITMAPFILEHEADER;
bfType ASCII B M, , ,
bitmap. 0x42
0x4D.
Windows . , WORD
, , , ,
bfType = 0x4d42.
bfSize .
bfOffbits .
BMP , bfOffbits
aBitmapBits.
bmiHeader,
.
BITMAPINFOHEADER wingdi.h:
typedef
DWORD
LONG
LONG
WORD
WORD
DWORD
DWORD
struct
tagBITMAPINFOHEADER{
biSize;
// BITMAPINFOHEADER
biWidth;
//
biHeight;
// +
biPlanes;
// ( 1)
biBitCount;
//
biCompression;
//
biSizeImage;
//
177
LONG
biXPelsPerMeter; //
LONG
biYPelsPerMeter; //
DWORD biClrUsed;
//
DWORD biClrImportant; // ,
//
} BITMAPINFOHEADER;
biWidth biHeight .
biHeight ,
.
.
( ),
. DIB
(bottomup).
( ), DIB (topdown).
BMP
.
biPlanes
.
( ). DIB
, biPlanes
.
biBitCount ,
. .
. 3.4.
3.4. biBitCount
21 (2)
1/8
.
bmiColors , RGBQUAD.
aBitmapBits
bmiColors. 0,
bmiColors[0], 1
bmiColors[1]
24 (16)
1/2
16 , , bmiColors
16 RGBQUAD.
aBitmapBits .
4-
28 (256)
256 , bmiColors
256 .
aBitmapBits
.
JPEG PNG ( Windows 98/2000)
178
3. GDI. , ,
3.4 ()
16
216 (
High Color). biCompression
BI_RGB, bmiColors
. (WORD)
aBitmapBits .
,
.
biCompression BI_BITFIELDS,
,
aBitmapBits
24
bmiColors
aBitmapBits ,
.
bmiColors
, .
, biClrUsed
32
224 (32-
True Color). biCompression
BI_RGB, bmiColors
.
(DWORD) aBitmapBits
.
,
.
.
biCompression BI_BITFIELDS,
,
aBitmapBits5
179
3.5. biCompression
BI_RGB
0x0
BI_RLE8
0x1
8 /,
RLE
BI_RLE4
0x2
4 /,
RLE
BI_BITFIELDS
0x3
16 32 /. ,
RGB
biCompression BI_RGB.
Microsoft, Visual Studio BMP
.
.
. 3.4.
, .
DIB 4 8 /
RLE (RunLength
Encoding). 8
, ,
.
, .
RLE [6].
BITMAPINFOHEADER biSizeImage,
. biCompression
BI_RGB, biSizeImage . GDI
, .
RLE, JPEG PNG
.
biXPelsPerMeter biYPelsPerMeter , ,
. ,
,
.
biClrUsed . DIB
, 256, biClrUsed
, . 3.4.
BMP, ,
.
DIB, .
biClrImportant ,
. ,
.
, BITMAPINFOHEADER
3 . Win32
180
3. GDI. , ,
,
.
.
DIB,
256 . aBitmapBits
. DIB
True Color (Hi Color), , , .
, True Color, .
biClrUsed
. ,
.
aBitmapBits. biHeight
,
,
.
.
.
:
bytesPerLine = ((width * bitCount + 31) / 32) * 4;
width , bitCount .
1
181
-
DIB, ,
.
(packed) DIB. DIB,
bmfHeader. , DIB
bmiHeader, , ,
( ) .
DIB GDI BITMAPINFO.
,
. ,
DIB .
, Win32 API,
DIB. , DIB
Windows.
DIB
DIB
StretchDIBits SetDIBitsToDevice.
StretchDIBits :
int
StretchDIBits(
HDC hdc,
//
int XDest,
// x-
int YDest,
// y-
int nDestWidth,
//
int nDestHeight,
//
int XSrc,
// x-
int YSrc,
// y-
int nSrcWidth,
//
int nSrcHeight,
//
CONST VOID* lpBits,
//
CONST BITMAPINFO* lpBitsInfo, //
UINT iUsage,
//
DWORD dwRop
//
);
1, DIB
, . ,
1
x y .
182
3. GDI. , ,
,
.
,
. :
wBmp ;
hBmp ;
xs XSrc;
ys YSrc;
ws nSrcWidth;
hs nSrcHeight;
xd XDest;
yd YDest;
wd nDestWidth;
hd nDestHeight.
,
.
. 3.6.
3.6.
[xs, ys, ws, hs]
0, 0, wBmp, hBmp
wBmp, 0, wBmp, hBmp
0, hBmp, wBmp, hBmp
wBmp, hBmp, wBmp, hBmp
0, 0, wBmp, 1
,
,
,
,
0, 0, 1, hBmp
SetStretchBltMode(HDC
hdc,
int
iStretchMode);
183
iStretchMode , . 3.7.
3.7.
( )
STRETCH_ANDSCANS
(BLACKONWHITE)
0x1
STRETCH_ORSCANS
(WHITEONBLACK)
0x2
STRETCH_DELETESCANS
(COLORONCOLOR)
0x3
STRETCH_HALFTONE (HALFTONE)
0x4
StretchDIBits.
lpBits . ,
.
lpBitsInfo .
BITMAPINFO, Win32 GDI
:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD
bmiColors[1];
} BITMAPINFO;
,
.
.
iUsage
DIB_RGB_COLORS, RGB ,
DIB_PAL_COLORS, .
, dwRop, .
,
SRCCOPY,
.
SetDIBitsToDevice. DIB ,
. ,
StretchDIBits
SetDIBitsToDevice.
, ,
, .
MSDN.
DIB
,
.
, BMP.
BMP, .
DIB C++,
KDib. .
184
3. GDI. , ,
,
. , KDib,
, .
BMP- ANSI-
, 3.5,
ANSI, ,
BMP. ANSI
True Color 24 /.
.
,
, SYSTEM_FONT. ,
,
, , 256
1.
KDib, , .
KDib.h, KDib.cpp.
3.5. CreateCharBmp
//////////////////////////////////////////////////////////////////////
// KDib.h
#include <windows.h>
#include <fstream>
#include <string>
using namespace std;
class KDib {
public:
KDib();
~KDib();
BOOL CreateDib24(int w, int h, const char* fileName);
void StoreDib24();
BOOL LoadFromFile(const char* fileName);
void SetPixel(int x, int y, COLORREF color);
int Draw(HDC hdc, int xDst, int yDst, int wDst, int hDst,
int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop);
int GetWidth() { return width; }
int GetHeight() { return height; }
const char* GetError() { return error.c_str(); }
private:
int width;
int height;
int bytesPerLine;
BITMAPFILEHEADER fileHead;
//
BITMAPINFOHEADER infoHead;
//
BITMAPINFOHEADER* pInfoHead;
BYTE* aBitmapBits;
//
int fileHeadSize;
int infoHeadSize;
1
,
.
185
int imageSize;
string error;
ifstream inpFile;
ofstream outFile;
};
//////////////////////////////////////////////////////////////////////
// KDib.cpp
#include "KDib.h"
KDib::KDib() {
fileHeadSize = sizeof(BITMAPFILEHEADER);
fileHead.bfType = 0x4d42;
aBitmapBits = NULL;
}
//====================================================================
KDib::~KDib() {
if (pInfoHead) delete [] pInfoHead;
if (aBitmapBits) delete [] aBitmapBits;
if (outFile) outFile.close();
}
//====================================================================
BOOL KDib::CreateDib24(int w, int h, const char* fileName) {
width = w;
height = h;
bytesPerLine = ((width * 24 + 31) / 32) * 4;
imageSize = bytesPerLine * height;
infoHeadSize = sizeof(BITMAPINFOHEADER);
fileHead.bfSize = fileHeadSize + infoHeadSize + bytesPerLine * height;
fileHead.bfOffBits = fileHeadSize + infoHeadSize;
infoHead.biSize = infoHeadSize;
infoHead.biWidth = width;
infoHead.biHeight = height;
infoHead.biPlanes = 1;
infoHead.biBitCount = 24;
infoHead.biCompression = BI_RGB;
infoHead.biSizeImage = imageSize;
aBitmapBits = new BYTE[imageSize];
memset(aBitmapBits, 0, imageSize);
outFile.open(fileName, ios::out | ios::binary | ios::trunc);
if (!outFile) return FALSE;
else return TRUE;
}
//====================================================================
BOOL KDib::LoadFromFile(const char* fileName) {
inpFile.open(fileName, ios::in | ios::binary);
if (!inpFile) {
error = " .";
return FALSE;
}
inpFile.read((char*)&fileHead, fileHeadSize);
if (fileHead.bfType != 0x4d42) {
error = " BMP-";
186
3. GDI. , ,
3.5 ()
return FALSE;
}
infoHeadSize = fileHead.bfOffBits - fileHeadSize;
int fileSize = fileHead.bfSize;
imageSize = fileSize - (fileHeadSize + infoHeadSize);
pInfoHead = (BITMAPINFOHEADER*)(new BYTE [infoHeadSize]);
inpFile.read((char*)pInfoHead, infoHeadSize);
width =
pInfoHead->biWidth;
height = pInfoHead->biHeight;
aBitmapBits = new BYTE[imageSize];
inpFile.read((char*)aBitmapBits, imageSize);
return true;
}
//====================================================================
int KDib::Draw(HDC hdc, int xDst, int yDst, int wDst, int hDst,
int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop) {
return StretchDIBits(hdc, xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc,
aBitmapBits, (CONST BITMAPINFO*)pInfoHead, DIB_RGB_COLORS, rop);
}
//====================================================================
void KDib::SetPixel(int x, int y, COLORREF color) {
int row = y;
int col = 3 * x;
aBitmapBits[row*bytesPerLine + col]
= GetBValue(color);
aBitmapBits[row*bytesPerLine + col+1] = GetGValue(color);
aBitmapBits[row*bytesPerLine + col+2] = GetRValue(color);
}
//====================================================================
void KDib::StoreDib24() {
// BMP-
outFile.write((char*)&fileHead, fileHeadSize);
outFile.write((char*)&infoHead, infoHeadSize);
//
outFile.write((char*)aBitmapBits, imageSize);
}
//////////////////////////////////////////////////////////////////////
// CreateCharBmp.cpp
#include <windows.h>
#include "KWnd.h"
#include "KDib.h"
#define ANSI_CODE 65
#define FILE_NAME "symbol.bmp"
KDib bmp;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
187
KWnd
mainWnd("CreateCharBmp",
hInstance,
nCmdShow,
WndProc);
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
TEXTMETRIC tm;
SIZE sz;
static int width, height;
COLORREF color;
int x, y;
BOOL isFileCreated;
static char line[2];
switch (uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
GetTextMetrics(hDC, &tm);
line[0] = ANSI_CODE;
line[1] = 0;
GetTextExtentPoint32(hDC, line, 1, &sz);
width = sz.cx;
height = tm.tmHeight;
isFileCreated =
bmp.CreateDib24(width, height, FILE_NAME);
if (!isFileCreated)
MessageBox(hWnd, " " FILE_NAME " .", "Error", MB_OK);
ReleaseDC(hWnd, hDC);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
SetBkColor(hDC, RGB(0,0,0));
SetTextColor(hDC, RGB(255,255,255));
TextOut(hDC, 0, 0, line, 1);
// ( )
// DIB
for (y = 0; y < height; ++y)
{
for (x = 0; x < width; ++x) {
color = GetPixel(hDC, x, height-1-y);
bmp.SetPixel(x, y, color);
}
}
bmp.StoreDib24();
EndPaint(hWnd, &ps);
188
3. GDI. , ,
3.5 ()
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
,
KDib. , ,
DIB.
, width, height, bytesPerLine, fileHead, infoHead aBitmapBits,
. BITMAPINFOHEADER,
pInfoHead? , LoadFromFile,
, ,
new.
, ,
/ . ,
, ,
.
,
, KDib , :
CreateDib24 24
.
.
.
, .
SetPixel 24 .
,
aBitmapBits.
y x.
StoreDib24 ,
BMP.
LoadFromFile BMP ,
.
,
, infoHeadSize.
imageSize
.
pInfoHead
aBitmapBits.
.
Draw ,
StretchDIBits.
189
CreateCharBmp.cpp.
, :
bmp KDib.
ANSI_CODE, ANSI. 65
A .
FILE_NAME, BMP,
.
WndProc,
:
WM_CREATE
tm GetTextMetrics.
, height.
C line,
.
ANSI_CODE, .
, ANSI_CODE.
GetTextExtentPoint32
line. width.
bmp.CreateDib24 DIB
.
WM_PAINT
. TextOut,
.
GetPixel.
bmp.SetPixel.
bmp.StoreDib24.
, 1.
symbol.bmp, ,
. 3.6. 8 MS PAINT.
.
. 3.6. symbol.bmp
KDib. ,
LoadFromFile Draw .
1
190
3. GDI. , ,
BMP-
, 3.6,
BMP. .
. .
, ,
. . ,
,
.
KDib,
. ,
. KDib.h KDib.cpp
.
3.6. BmpFileViewer
//////////////////////////////////////////////////////////////////////
// BmpFileViewer.cpp
#include <windows.h>
#include "KWnd.h"
#include "KDib.h"
#define
FILE_NAME
"YoungHacker.bmp"
KDib bmp;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("BmpFileViewer", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
int dX, dY;
int ws, hs, wd, hd;
static BOOL isFileLoaded;
switch (uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
isFileLoaded = bmp.LoadFromFile(FILE_NAME);
191
if (!isFileLoaded) {
MessageBox(hWnd, " " FILE_NAME " .", "Error",
MB_OK);
MessageBox(hWnd, bmp.GetError(), "Error", MB_OK);
break;
}
// bmp
GetClientRect(hWnd, &rect);
dX = bmp.GetWidth() - rect.right;
dY = bmp.GetHeight() - rect.bottom;
GetWindowRect(hWnd, &rect);
InflateRect(&rect, dX/2, dY/2);
MoveWindow(hWnd, rect.left, rect.top,
rect.right-rect.left, rect.bottom-rect.top, TRUE);
ReleaseDC(hWnd, hDC);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
wd = ws = bmp.GetWidth();
hd = hs = bmp.GetHeight();
bmp.Draw(hDC, 0, 0, wd, hd, 0, 0, ws, hs, SRCCOPY);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
, , , ,
BMP, .
YoungHacker.bmp. ?
www.piter.com
.
. , BMP,
.
.
, . 3.7.
bmp.Draw,
StretchDIBits. ,
( )
.
StretchDIBits. .
:
int xd0, yd0, xd1, yd1, xd2, yd2, xd3, yd3;
192
3. GDI. , ,
. 3.8. BmpFileViewer
193
WM_PAINT :
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
ws = bmp.GetWidth();
hs = bmp.GetHeight();
wd = ws/2 - 4;
hd = hs/2 - 4;
xd0 = 2;
yd0 = 2;
xd1 = ws/2 + 2; yd1 = 2;
xd2 = 2;
yd2 = hs/2 + 2;
xd3 = ws/2 + 2; yd3 = hs/2 + 2;
SetStretchBltMode(hDC, STRETCH_HALFTONE);
bmp.Draw(hDC, xd0, yd0, wd, hd, ws, 0, -ws, hs, SRCCOPY);
bmp.Draw(hDC, xd1, yd1, wd, hd, 0, 0, ws, hs, SRCCOPY);
bmp.Draw(hDC, xd2, yd2, wd, hd, ws, hs, -ws, -hs, SRCCOPY);
bmp.Draw(hDC, xd3, yd3, wd, hd, 0, hs, ws, -hs, SRCCOPY);
EndPaint(hWnd, &ps);
return 0;
, . 3.8.
-
(DDB) GDI,
GDI .
, . DDB
Windows
GDI.
GDI, HBITMAP. DDB
GDI. , DDB ,
.
DDB-
Win32 GDI GDI:
HBITMAP
UINT
HBITMAP
HBITMAP
194
3. GDI. , ,
LONG
bmWidthBytes; //
//( )
WORD
bmPlanes;
//
WORD
bmBitsPixel;
//
LPVOID bmBits;
//
} BITMAP;
, ,
.
, , ,
. lpvBits
lpbm.bmBits NULL. ,
, ,
,
.
CreateCompatibleBitmap DDB
,
hdc. , ,
.
DDB- DIB
,
DDB.
.
GDI CreateDIBitmap,
DDB DIB, , , DIB DDB.
:
HBITMAP CreateDIBitmap(HDC hdc,
CONST BITMAPINFOHEADER* lpbmih,
DWORD fdwInit, CONST VOID* lpbInit, CONST BITMAPINFO* lpbmi,
UINT fuUsage);
DDB,
hdc, DIB DDB. lpbmih
DIB. fdwInit
DDB. CBM_INIT,
DIB,
. lpbInit , lpbmi
DIB, BITMAPINFO.
, fuUsage, ,
(DIB_PAL_COLORS) RGB (DIB_RGB_COLORS).
, , ,
DIB , , , 3.6,
. StretchDIBits ( KDib
Draw). CreateDIBitmap
DIB, , DDB,
BitBlt (
DDB ). :
?
DDB
.
195
DDB-
Windows DIB (BMP)
1, LoadBitmap,
HBITMAP:
HBITMAP LoadBitmap(
HINSTANCE hInstance,
LPCTSTR lpBitmapName
);
//
//
5,
, szBmpName1, ,
IDB_1. lpBitmapName
szBmpName1, ,
LPCTSTR MAKEINTRESOURCE,
MAKEINTRESOURCE(IDB_1).
Win32 DIB
. LoadBitmap , ,
DIB DDB
, .
LoadBitmap 5.4
12.1.
LoadBitmap
,
Win32 API. hInstance NULL,
OBM_BTNCORNERS, OBM_BTSIZE
.
DDB- BMP-
,
BMP,
LoadImage, , .
:
HANDLE LoadImage(
HINSTANCE hinst,
LPCTSTR lpszName,
UINT uType,
int cxDesired,
int cyDesired,
UINT fuLoad
);
//
//
//
//
//
//
lpszName,
fuLoad LR_LOADFROMFILE, uType
IMAGE_BITMAP. cxDesired cyDesired
.
DDB. ,
NULL.
LoadImage 3.7.
1
Windows 5.
196
3. GDI. , ,
DDB
, .
GetObject,
:
int GetObject(
HGDIOBJ hgdiobj,
int cbBuffer,
LPVOID lpvObject
);
//
//
//
, hgdiobj
, , , ,
HBITMAP.
lpvObject. . 3.7 ,
.
3.7. , lpvObject
HBITMAP
BITMAP
HBITMAP,
CreateDIBSection
DIBSECTION, cbBuffer
sizeof(DIBSECTION), BITMAP, cbBuffer
sizeof(BITMAP)
HPALETTE
WORD
HPEN
LOGPEN
HPEN,
ExtCreatePen
EXTLOGPEN
HBRUSH
LOGBRUSH
HFONT
LOGFONT
lpvObject NULL,
, lpvObject
.
lpvObject NULL,
.
.
GetObject HBITMAP,
,
. bmBits BITMAP
.
DDB-
DDB Windows
, Win32 API DDB.
GDI DDB ,
(
) ().
, .
197
?
,
. GDI
( ). 2
. ,
:
HDC CreateCompatibleDC (HDC hdc);
hdc ,
. CreateCompatibleDC
, . hdc
,
. NULL,
, .
, .
,
. ,
, DDB SelectObject.
DDB hBitmap
hDC
:
//
HDC hMemDC;
//
hMemDC = CreateCompatibleDC(hDC);
// DDB-
SelectObject(hMemDC, hBitmap);
// hMemDC hDC
BitBlt(hDC, 0, 0, bmpWidth, bmpHeight, hMemDC, 0, 0, SRCCOPY);
//
DeleteDC(hMemDC);
,
.
hDC hMemDC, DDB.
1 GDI BitBlt StretchBlt.
.
BitBlt bit block transfer,
. BitBlt
, .
256 .
:
BOOL BitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop);
BitBlt
hdcSrc hdcDest.
nXSrc, nYSrc, nWidth, nHeight
1
198
3. GDI. , ,
.
nXDest, nYDest, nWidth, nHeight
.
RC_BITBLT.
,
nWidth
nHeight.
MM_TEXT,
,
.
.
.
. BitBlt
, .
dwRop ,
,
. ,
SRCCOPY,
.
StretchBlt :
BOOL StretchBlt(HDC hdcDest, int nXDest, int nYDest, int nWidthDest,
int nHeightDest, HDC hdcSrc, int nXSrc, int nYSrc, int nWidthSrc,
int nHeightSrc, DWORD dwRop);
, BitBlt,
.
,
.
, StretchDIBits,
( )
, . 3.6.
DDB
, 3.7, DDB BMP
, . ,
, BmpFileViewer (. 3.6),
.
3.7. BmpFileViewer2
//////////////////////////////////////////////////////////////////////
// BmpFileViewer2.cpp
#include <windows.h>
#include "KWnd.h"
#define
FILE_NAME
"YoungHacker.bmp"
199
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("BmpFileViewer2", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
static int bmpWidth, bmpHeight;
static HBITMAP hBitmap;
//
HINSTANCE hInst;
HDC hMemDC;
//
BITMAP bm;
int dX, dY;
switch (uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
hInst = (HINSTANCE)GetClassLong(hWnd, GCL_HMODULE);
hBitmap = (HBITMAP)LoadImage(hInst, FILE_NAME, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE);
if (hBitmap == NULL) {
MessageBox(hWnd, " " FILE_NAME " ", "Error", MB_OK);
break;
}
GetObject(hBitmap, sizeof(bm), &bm);
bmpWidth = bm.bmWidth;
bmpHeight = bm.bmHeight;
// hBitmap
GetClientRect(hWnd, &rect);
dX = bmpWidth - rect.right;
dY = bmpHeight - rect.bottom;
GetWindowRect(hWnd, &rect);
InflateRect(&rect, dX/2, dY/2);
MoveWindow(hWnd, rect.left, rect.top,
rect.right-rect.left, rect.bottom-rect.top, TRUE);
ReleaseDC(hWnd, hDC);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
//
hMemDC = CreateCompatibleDC(hDC);
200
3. GDI. , ,
3.7. ()
// hBitmap
SelectObject(hMemDC, hBitmap);
// hMemDC hDC
BitBlt(hDC, 0, 0, bmpWidth, bmpHeight, hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
. , DDB
hBitmap WM_CREATE
LoadImage. hInst,
LoadImage,
GetClassLong(hWnd, GCL_HMODULE).
GetObject.
WM_PAINT .
( ) hMemDC,
hBitmap.
BitBlt. .
,
BmpFileViewer (. . 3.7).
DIB-
. DDB DIB . 3.8.
3.8. DDB DIB
DDB
DIB
GDI
48 M ( )
(
)
201
DIB-
DIB CreateDIBSection:
HBITMAP CreateDIBSection(
HDC hdc,
//
CONST BITMAPINFO* pbmi, //
UINT iUsage,
//
VOID** ppvBits,
//
HANDLE hSection, // ,
DWORD dwOffset
//
);
BITMAPINFO, .
, , . DIB
BI_RGB, .
, , ,
.
iUsage , bmiColors,
BITMAPINFO. iUsage
DIB_PAL_COLORS, bmiColors
. DIB_RGB_COLORS ,
RGB.
ppvBits , GDI
DIB.
hSection NULL. GDI
, dwOffset
. hSection NULL,
, ,
CreateFileMapping PAGE_READWRITE PAGE_WRITECOPY.
,
dwOffset.
,
DIB (. KDib 3.5).
DIB
KDibSection, 12,
(. 12.4).
202
3. GDI. , ,
DIB-
DIB
:
DIB StretchDIBits SetDIBitsToDevice;
GDI, hBitmap,
BitBlt StretchBlt.
DIB ArincReceiver (
12, 12.4).
, dwRop, BitBlt, PatBlt StretchBlt
, GDI,
.
. ,
.
Win32 API 256 ROP (rasteroperation codes).
32 DWORD.
256 ,
,
.
Microsoft
256. , ,
.
. 3.9, : P
(pattern), S (source), D (destination).
3.9.
Pattern:
Source:
Destination:
11110000
11001100
10101010
ROP-
0
0
0
0
0
0
0
1
1
1
1
1
1
1
D=0
D = ~(S | D)
D = ~S
D = S & ~D
D = ~D
D=P^D
D=S^D
D=S&D
D = ~S | D
D=P&S
D=S
D=S|D
D=P
D = P | ~S | D
0x00000042
0x001100A6
0x00330008
0x00440328
0x00550009
0x005A0049
0x00660046
0x008800C6
0x00BB0226
0x00C000CA
0x00CC0020
0x00EE0086
0x00F00021
0x00FB0A09
BLACKNESS
NOTSRCERASE
NOTSRCCOPY
SRCERASE
DSTINVERT
PATINVERT
SRCINVERT
SRCAND
MERGEPAINT
MERGECOPY
SRCCOPY
SRCPAINT
PATCOPY
PATPAINT
D=1
0x00FF0062
WHITENESS
0
0
0
1
1
1
1
0
0
1
1
1
1
1
0
0
1
0
0
0
1
0
1
0
0
1
1
1
0
1
1
0
1
1
0
0
1
0
0
0
1
1
0000
0001
0011
0100
0101
1010
0110
1000
1011
0000
1100
1110
0000
1011
11111111
203
MSDN
(Platform SDKWindows GDITernary Raster Operations).
,
. ,
, ROP.
. 3.9 ,
.
.
BLACKNESS WHITENESS , ,
.
. (Black) (White)
, 0,
1. C
:
Black
Black
Black
White
White
White
AND C
OR C
XOR C
AND C
OR C
XOR C
=
=
=
=
=
=
Black
C
C
C
White
NOT C
.
,
SRCCOPY NOTSRCCOPY.
SRCCOPY .
.
.
NOTSRCCOPY ,
.
,
DSTINVERT .
,
. 3.9 PATINVERT PATCOPY. 16
, ,
. GDI
, :
BOOL PatBlt(HDC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight,
DWORD dwRop);
PatBlt
. ROP 1,
, , . 3.9.
1
. MSDN.
204
3. GDI. , ,
,
NOTSRCERASE, SRCERASE, SRCINVERT, SRCAND, MERGEPAINT
SRCPAINT. , SRCINVERT SRCAND
Windows .
, , ,
Windows.
Shell32.dll1. ,
LoadLibrary,
(hShell32),
. , ,
hShell32. LoadImage.
, LoadImage 12,
, CDROM.
LoadImage
hIcon.
GetIconInfo(hIcon, &iconInfo);
,
iconInfo ICONINFO. :
HBITMAP hbmMask;
HBITMAP hbmColor;
,
, ,
. . 3.9
CDROM.
. 3.9. CD-ROM
48 48. ?
,
, .
,
.
.
, 3.8, ,
.
3.8. DrawIconWithRop
//////////////////////////////////////////////////////////////////////
// DrawIconWithRop.cpp
#include <windows.h>
1
5.
205
#include
"KWnd.h"
#define ICON_ID
12
206
3. GDI. , ,
3.8 ()
SelectObject(hMemDC, iconInfo.hbmColor);
BitBlt(hDC, x+60, y, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0,
SRCCOPY);
//
SelectObject(hMemDC, iconInfo.hbmMask);
BitBlt(hDC, x+120, y, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0,
SRCAND);
SelectObject(hMemDC, iconInfo.hbmColor);
BitBlt(hDC, x+120, y, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0,
SRCINVERT);
// DrawIcon
DrawIcon(hDC, x+188, y, hIcon);
DeleteObject(hMemDC);
DestroyIcon(hIcon);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
BitBlt
SRCAND .
, .
, BitBlt
SRCINVERT.
. 3.10.
: (), (), (),
, (),
DrawIcon,
32 32 .
. 3.10. DrawIconWithRop
GDI,
. ,
. ,
207
,
, , , ,
.
,
GDI.
,
,
, .
,
. ,
.
, .
,
.
.
16 WMF1 Windows 2.0.
,
. Win32 32 EMF (Enhanced Metafile
Format).
,
. , 32 . Win32
API WMF EMF.
EMF,
.
GDI, , ,
DIB.
HENHMETAFILE.
GDI
, .
CreateEnhMetaFile:
HDC CreateEnhMetaFile(HDC hdcRef, LPCTSTR lpFilename, CONST RECT* lpRect,
LPCTSTR lpDescription);
, hdcRef, ,
EMF.
NULL, GDI .
, lpFilename,
NULL. NULL, .
, DeleteEnhMetaFile
.
1
208
3. GDI. , ,
, lpRect,
0,01 . NULL, GDI
.
, lpDescription,
, .
, .
.
CreateEnhMetaFile
. GDI
.
, CloseEnhMetaFile,
.
.
,
CreateEnhMetaFile,
DeleteEnhMetaFile, .
,
3.9. CreateMetaFile
, ,
,
.
3.9. CreateMetaFile
//////////////////////////////////////////////////////////////////////
// CreateMetaFile.cpp
#include <windows.h>
#include "KWnd.h"
#define FILE_NAME "Pict1.emf"
void DrawSomething(HDC);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("CreateMetaFile", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
static HDC hdcEMF;
HENHMETAFILE hemf;
switch (uMsg)
{
case WM_CREATE:
hdcEMF = CreateEnhMetaFile(NULL, FILE_NAME, NULL,
"CreateMetaFile\0Pict1\0");
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
DrawSomething(hDC);
DrawSomething(hdcEMF);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
hemf = CloseEnhMetaFile(hdcEMF);
DeleteEnhMetaFile(hemf);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
void DrawSomething(HDC hdc) {
RECT r;
HPEN hPen, hOldPen;
HBRUSH hBrush, hOldBrush;
SetRect(&r, 20, 20, 220, 220);
hPen = CreatePen(PS_SOLID, 10, RGB(255, 160, 140));
hOldPen = (HPEN)SelectObject(hdc, hPen);
hBrush = CreateSolidBrush(RGB(140, 160, 255));
hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Rectangle(hdc, r.left, r.top, r.right, r.bottom);
hPen = CreatePen(PS_SOLID, 3, RGB(0, 255, 0));
SelectObject(hdc, hPen);
hBrush = CreateSolidBrush(RGB(100, 100, 100));
SelectObject(hdc, hBrush);
InflateRect(&r, -40, -40);
Ellipse(hdc, r.left, r.top, r.right, r.bottom);
SetTextColor(hdc, RGB(255, 255, 255));
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, "YES !", -1, &r, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
DeleteObject(SelectObject(hdc, hOldPen));
DeleteObject(SelectObject(hdc, hOldBrush));
}
//////////////////////////////////////////////////////////////////////
209
210
3. GDI. , ,
WM_CREATE. hdcEMF static,
,
.
DrawSomething,
hdc, .
,
200 200 , ,
.
WM_PAINT DrawSomething
: , .
WM_DESTROY :
hemf = CloseEnhMetaFile(hdcEMF);
DeleteEnhMetaFile(hemf);
.
.
, . 3.11.
True Color, , , ,
, ,
, , .
. 3.11. CreateMetaFile
, .
.
Pict1.emf. .
,
EMF, , ACDSee.
PlayEnhMetaFile,
:
BOOL PlayEnhMetaFile(HDC hdc, HENHMETAFILE hemf, CONST RECT* lpRect);
, hdc, .
.
hdc.
211
, .
GetEnhMetaFileHeader:
HENHMETAFILE GetEnhMetaFile(LPCTSTR lpszMetaFile);
lpszMetaFile.
, lpszMetaFile
.
:
PlayEnhMetaFile?
GetEnhMetaFileHeader,
ENHMETAHEADER, rclBounds
.
3.10 ,
Pict1.emf.
PlayMetaFile.
3.10. PlayMetaFile
//////////////////////////////////////////////////////////////////////
//
PlayMetaFile.cpp
#include <windows.h>
#include "KWnd.h"
#define FILE_NAME "Pict1.emf"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("PlayMetaFile", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
HENHMETAFILE hemf;
ENHMETAHEADER emh;
int x1, y1, x2, y2;
switch (uMsg)
{
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
hemf = GetEnhMetaFile(FILE_NAME);
212
3. GDI. , ,
3.10 ()
if (!hemf)
MessageBox(hWnd, " " FILE_NAME " .", "Error", MB_OK);
else {
GetEnhMetaFileHeader(hemf, sizeof(ENHMETAHEADER), &emh);
x1 = emh.rclBounds.left; y1 = emh.rclBounds.top;
x2 = emh.rclBounds.right; y2 = emh.rclBounds.bottom;
SetRect(&rect, x1, y1, x2, y2);
PlayEnhMetaFile(hDC, hemf, &rect);
DeleteEnhMetaFile(hemf);
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
,
SetRect(&rect, x1, y1, x2, y2);
:
SetRect(&rect,
SetRect(&rect,
SetRect(&rect,
SetRect(&rect,
x1,
x1,
x1,
x1,
y1,
y1,
y1,
y1,
2 * x2, y2);
x2, 2 * y2);
2 * x2, 2 * y2);
0.5* x2, 0.5 * y2);
, .
213
, Windows,
,
.
, , ,
.
. , ,
, . Win32 API
.
Windows ,
, .
.
1.
. 4.1 ,
.
. 4.1.
1
,
.
214
4.
,
. (scan
code) ,
1.
,
.
(virtualkey code). ,
Windows
. ,
, /
. .
Windows
, .
,
.
, Windows,
.
,
. Windows ,
. (keyboard focus) ,
,
. , ,
.
.
,
. ,
. , Windows
.
,
. ,
, , ,
. ,
. , ,
, , .
, . Windows
,
, ,
.
WM_SETFOCUS WM_KILLFOCUS,
.
, ,
.
1
215
:
HWND SetFocus(HWND hWnd) hWnd,
, .
HWND GetFocus() ,
.
,
,
.
, . ,
,
. ANSI1.
.
, .
, ,
,
.
:
Caps Lock, Num Lock, Scroll Lock
Insert. ,
. ,
.
, , ,
, Pause, Delete.
, , , Tab, Backspace,
Esc Enter. , Tab, Backspace, Esc Enter
.
, Windows,
(keystrokes) (characters).
.
. 4.1.
.
SYS .
1
. 2, .
216
4.
4.1.
WM_KEYDOWN
WM_KEYUP
WM_SYSKEYDOWN
WM_SYSKEYUP
WM_SYSKEYDOWN WM_SYSKEYUP,
Alt, Windows,
.
. ,
(Alt + Tab), (Alt
). Windows
Alt, , ,
.
,
(, ).
.
,
, Windows WM_KEYDOWN
WM_KEYUP, , , .
32 lParam,
, 6 (. 4.2).
4.2. lParam
15 . . . 0
. ,
, .
WM_KEYUP
23 . . . 16
C-
- OEM
24
29
30
, , ,
31
, , ,
lParam
, wParam,
.
(virtual key code)
.
winuser.h. . 4.3
.
217
4.3.
IBM
03
VK_CANCEL
Ctrl + Break
08
VK_BACK
Backspace
09
VK_TAB
Tab
13
0D
VK_RETURN
Enter
16
10
VK_SHIFT
Shift
17
11
VK_CONTROL
Ctrl
18
12
VK_MENU
Alt
19
13
VK_PAUSE
Pause
20
14
VK_CAPITAL
Caps Lock
27
1B
VK_ESCAPE
Esc
32
20
VK_SPACE
33
21
VK_PRIOR
Page Up
34
22
VK_NEXT
Page Down
35
23
VK_END
End
36
24
VK_HOME
Home
37
25
VK_LEFT
38
26
VK_UP
39
27
VK_RIGHT
40
28
VK_DOWN
44
2C
VK_SNAPSHOT
Print Screen
45
2D
VK_INSERT
Insert
46
2E
VK_DELETE
4857
3039
6590
415A
112123
707B
Delete
09 (
)
AZ
VK_F1VK_F12
F1F12
144
90
VK_NUMLOCK
Num Lock
145
91
VK_SCROLL
Scroll Lock
, . ,
WM_KEYDOWN,
, Shift
.
. ,
, WM_CHAR.
,
.
, ,
218
4.
. TranslateMessage,
, WinMain
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
, GetMessage
msg, DispatchMessage
.
TranslateMessage,
. WM_KEYDOWN,
, TranslateMessage .
WM_KEYDOWN
WM_CHAR WM_DEADCHAR.
WM_DEADCHAR.
(dead keys), ,
, .
, . ,
U (U)
, U. ,
WM_DEADCHAR, Windows
, WM_CHAR,
ANSI .
,
WM_CHAR. lParam WM_CHAR,
, , lParam
. wParam ANSI.
. , Caps
Lock 1, A,
:
WM_KEYDOWN
WM_CHAR
ANSI- a
WM_KEYUP
, Shift, A,
A Shift,
:
1
Caps Lock
<Caps Lock>.
219
WM_KEYDOWN
WM_KEYDOWN
WM_CHAR
WM_KEYUP
VK_SHIFT
A
ANSI- A
A
WM_KEYUP
VK_SHIFT
. ,
, ,
. ,
,
.
Win32 API ,
:
CreateCaret .
SetCaretPos .
ShowCaret .
HideCaret .
DestroyCaret .
WM_CREATE WM_DESTROY.
. ,
, .
, ,
WM_SETFOCUS WM_KILLFOCUS.
.
CreateCaret WM_SETFOCUS
DestroyCaret WM_KILLFOCUS.
CreateCaret,
:
,
.
.
, NULL.
hBitmap NULL,
nWidth nHeight, .
hBitmap , ,
NULL,
, .
.
220
4.
hBitmap ,
. nWidth nHeight .
nWidth nHeight
. . nWidth
,
, . nHeight
, ,
1.
CreateCaret
. .
CreateCaret .
, ShowCaret.
DestroyCaret
HideCaret.
Typer, 4.1,
.
.
, ,
Enter,
, ,
, .
, ,
.
, ,
string C++
C.
,
.
string,
:
#include <string>
using namespace std;
( string)
:
static string text;
static
text 2.
, string,
, .
1
GetSystemMetrics (SM_CXBORDER) GetSystemMetrics (SM_CYBORDER) .
, static,
WndProc.
221
symb
+= :
text += symb;
insert symb
index:
text.insert(index, symb);
n , index, erase:
text.erase(index, n);
size, , , :
nLines = text.size() / nCharPerLine;
, text
C c_str. TextOut,
C.
WM_KEYDOWN, WM_CHAR, WM_SETFOCUS,
WM_KILLFOCUS, Typer
.
.
4.1. Typer1
//////////////////////////////////////////////////////////////////////
// Typer.cpp
#include <windows.h>
#include <string>
using namespace std;
#include KWnd.h
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd(Typer, hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
222
4.
4.1 ()
TEXTMETRIC tm;
static string text; //
string symb;
static int cxChar, cyChar, cxClient, cyClient;
static int nCharPerLine, nClientLines;
static int xCaret = 0, yCaret = 0;
int curIndex;
int nLines; //
int nTailChar; //
int x, y, i;
switch (uMsg) {
case WM_CREATE:
hDC = GetDC(hWnd);
SelectObject(hDC, GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hDC, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight;
ReleaseDC(hWnd, hDC);
break;
case WM_SIZE:
//
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
// ( 'x') ( 'y')
nCharPerLine = max(1, cxClient / cxChar);
nClientLines = max(1, cyClient / cyChar);
if (hWnd == GetFocus())
SetCaretPos(xCaret * cxChar, yCaret * cyChar);
break;
case WM_SETFOCUS:
//
CreateCaret(hWnd, NULL, 0, cyChar);
SetCaretPos(xCaret * cxChar, yCaret * cyChar);
ShowCaret(hWnd);
break;
case WM_KILLFOCUS:
//
HideCaret(hWnd);
DestroyCaret();
break;
case WM_KEYDOWN:
nLines = text.size() / nCharPerLine;
nTailChar = text.size() % nCharPerLine;
switch (wParam) {
case VK_HOME:
xCaret = 0;
break;
223
case VK_END:
if (yCaret == nLines)
xCaret = nTailChar;
else
xCaret = nCharPerLine - 1;
break;
case VK_PRIOR: yCaret = 0;
break;
case VK_NEXT:
yCaret = nLines;
xCaret = nTailChar;
break;
case VK_LEFT:
xCaret = max(xCaret - 1, 0);
break;
case VK_RIGHT: xCaret = min(xCaret + 1, nCharPerLine - 1);
if ((yCaret == nLines) && (xCaret > nTailChar))
xCaret = nTailChar;
break;
case VK_UP:
yCaret = max(yCaret - 1, 0);
break;
case VK_DOWN:
yCaret = min(yCaret + 1, nLines);
if ((yCaret == nLines) && (xCaret > nTailChar))
xCaret = nTailChar;
break;
case VK_DELETE: curIndex = yCaret * nCharPerLine + xCaret;
if (curIndex < text.size()) {
text.erase(curIndex, 1);
InvalidateRect(hWnd, NULL, TRUE);
}
break;
}
SetCaretPos(xCaret * cxChar, yCaret * cyChar);
break;
case WM_CHAR:
switch (wParam) {
case '\b': // 'backspace'
if (xCaret > 0) {
xCaret--;
SendMessage(hWnd, WM_KEYDOWN, VK_DELETE, 1);
}
break;
case '\t': // 'tab'
do { SendMessage(hWnd, WM_CHAR, ' ', 1L); }
while (xCaret % 8 != 0);
break;
case '\r': case '\n': //
for (i = 0; i < nCharPerLine - xCaret; ++i)
text += ' ';
xCaret = 0;
if (++yCaret == nClientLines) {
MessageBox(hWnd, " ", "Error", MB_OK);
yCaret--;
}
224
4.
4.1 ()
break;
default: //
curIndex = yCaret * nCharPerLine + xCaret;
if (curIndex == text.size())
text += (char)wParam;
else {
symb = (char)wParam;
text.insert(curIndex, symb);
}
InvalidateRect(hWnd, NULL, TRUE);
if (++xCaret == nCharPerLine) {
xCaret = 0;
if (++yCaret == nClientLines) {
MessageBox(hWnd, " ", "Error", MB_OK);
yCaret--;
}
}
break;
}
SetCaretPos(xCaret * cxChar, yCaret * cyChar);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
SelectObject(hDC, GetStockObject(SYSTEM_FIXED_FONT));
if (text.size()) {
nLines = text.size() / nCharPerLine;
nTailChar = text.size() % nCharPerLine;
for (y = 0; y < nLines; ++y)
TextOut(hDC, 0, y*cyChar, text.c_str() + y*nCharPerLine,
nCharPerLine);
TextOut(hDC, 0, y*cyChar, text.c_str() + y*nCharPerLine,
nTailChar);
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
,
Typer. .
WM_SETFOCUS :
225
CreateCaret(hWnd, 1, 0, cyChar);
CreateCaret(hWnd, 1, 10, cyChar);
, .
. Win32
API , ,
.
GetSystemMetrics:
fMouse = GetSystemMetrics (SM_MOUSEPRESENT);
, fMouse TRUE.
:
cButtons = GetSystemMetrics (SM_CMOUSEBUTTONS);
, .
, ,
.
,
, .
.
, ,
, .
Windows, Microsoft IntelliMouse.
,
,
, .
.
, , ,
.
, ,
,
.
GetSystemMetrics:
fMouseWheel = GetSystemMetrics(SM_MOUSEWHEELPRESENT);
TRUE, .
,
Windows , ,
.
,
.
226
4.
,
, Windows
, (mouse
cursor).
(hot spot) ,
. ,
. ,
(IDC_ARROW) .
, (IDC_CROSS),
.
, , ,
. ,
:
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
:
.
.
, .
,
Windows, LBUTTON, MBUTTON RBUTTON.
.
.
, , Windows
, .
Windows .
, , ,
.
,
WM_MOUSEMOVE.
,
:
( )
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_MBUTTONDOWN
WM_MBUTTONUP
WM_MBUTTONDBLCLK
WM_RBUTTONDOWN
WM_RBUTTONUP
WM_RBUTTONDBLCLK
lParam
. x,
y.
. lParam
LOWORD HIWORD.
227
wParam Shift
Ctrl. wParam
:
MK_LBUTTON
MK_MBUTTON
MK_RBUTTON
MK_SHIFT
Shift
MK_CONTROL
Ctrl
, Windows ,
WM_LBUTTONDOWN.
,
.
(Mouse), .
,
(DBLCLK) ,
CS_DBLCLKS.
style WNDCLASS , .
, KWnd,
:
style = GetClassLong(hWnd, GCL_STYLE);
SetClassLong(hWnd, GCL_STYLE, style | CS_DBLCLKS);
CS_DBLCLKS
,
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDOWN WM_LBUTTONUP.
CS_DBLCLKS,
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_ LBUTTONDBLCLK WM_LBUTTONUP. ,
WM_LBUTTONDOWN WM_LBUTTONDBLCLK.
WM_LBUTTONDBLCLK 4.4.
Windows ,
.
WM_MOUSEWHEEL.
,
:
#include <zmouse.h>
zmouse.h .
228
4.
wParam WM_MOUSEWHEEL
, ,
Shift Ctrl.
wParam ,
, .
, WHEEL_DELTA.
zmouse.h 120.
WM_MOUSEWHEEL ,
4.5.
.
, ,
.
, ,
, , , .
, .
Scribble ( 4.2).
4.2. Scribble
//////////////////////////////////////////////////////////////////////
// Scribble.cpp
#include <windows.h>
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("Scribble", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HDC hDC;
static int x, y; //
static BOOL bTracking = FALSE;
switch (uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
229
break;
case WM_LBUTTONDOWN:
bTracking = TRUE;
//
x = LOWORD(lParam);
y = HIWORD(lParam);
MoveToEx(hDC, x, y, NULL);
break;
case WM_LBUTTONUP:
bTracking = FALSE;
break;
case WM_MOUSEMOVE:
if (bTracking) {
//
x = LOWORD(lParam);
y = HIWORD(lParam);
LineTo(hDC, x, y);
}
break;
case WM_DESTROY:
ReleaseDC(hWnd, hDC);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
. , WM_LBUTTONDOWN,
bTracking TRUE
MoveToEx.
WM_MOUSEMOVE
. , bTracking
FALSE .
,
MoveToEx LineTo. hDC
static. .
GetDC WM_CREATE,
ReleaseDC WM_DESTROY. .
, ,
WM_PAINT. ,
.
hDC ,
,
LineTo, WndProc.
230
4.
. 4.2 Scribble.
. 4.2. Scribble
?.. ,
, ! ,
WM_PAINT,
!
.
WM_PAINT?
! ,
. ,
,
. ,
.
vector
STL. vector , ,
,
. string vector
.
vector,
:
#include <vector>
using namespace std;
vector ,
, :
vector<int> v1; // v1 - int
, , vector,
, .
v1, , ,
.
push_back:
v1.push_back(value);
int v1
value.
231
size.
,
, ,
.
v1:
vector<int>::iterator it; // it vector<int>
for (it = v1.begin(); it != v1.end(); ++it) {
// *it it
}
begin() , v1,
end() , ,
v1.
,
clear.
vector ,
.
,
.
x y. Win32 API POINT,
. , ,
:
static vector<POINT> curve;
, . , ,
POINT ,
1 POINT(x, y),
:
curve.push_back(POINT(x, y));
, Point,
:
struct Point {
Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}
int x;
int y;
};
,
, :
static vector<Point> curve;
, ,
WM_LBUTTONUP.
curve curves,
curve:
static vector<vector<Point> > curves;
1
, ,
(public). ,
.
232
4.
curves .
vector<Point>.
. ,
.
ScribbleAdvanced, Scribble,
4.3.
4.3. ScribbleAdvanced
//////////////////////////////////////////////////////////////////////
// ScribbleAdvanced.cpp
#include <windows.h>
#include <vector>
using namespace std;
#include "KWnd.h"
struct Point {
Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}
int x;
int y;
};
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("ScribbleAdvanced", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HDC hDC; //
HDC hdc; //
// WM_PAINT
PAINTSTRUCT ps;
static int x, y; //
static BOOL bTracking = FALSE;
static vector<Point> curve;
static vector<vector<Point> > curves;
vector<Point>::iterator it;
int i, j;
switch (uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
233
break;
case WM_LBUTTONDOWN:
bTracking = TRUE;
//
x = LOWORD(lParam);
y = HIWORD(lParam);
MoveToEx(hDC, x, y, NULL);
curve.push_back(Point(x, y));
break;
case WM_LBUTTONUP:
if (bTracking) {
bTracking = FALSE;
curves.push_back(curve);
curve.clear();
}
break;
case WM_MOUSEMOVE:
if (bTracking) {
//
x = LOWORD(lParam);
y = HIWORD(lParam);
LineTo(hDC, x, y);
curve.push_back(Point(x, y));
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
for (i = 0; i < curves.size(); ++i) {
it = curves[i].begin();
MoveToEx(hdc, it->x, it->y, NULL);
for (it + 1; it != curves[i].end(); ++it)
LineTo(hdc, it->x, it->y);
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
ReleaseDC(hWnd, hDC);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
, ,
WM_PAINT. ,
hdc,
hDC, .
234
4.
, curves
, (
vector<Point>) it.
: , , it
*it? , , ,
Point, x y.
LineTo :
LineTo(hdc, (*it).x, (*it).y);
. C++
, (*it).x
it->x. LineTo :
LineTo(hdc, it->x, it->y);
, .
, ,
. ,
,
.
, ,
. ,
, , .
ElasticRect, 4.4,
. ,
, .
, .
.
. WM_MOUSEMOVE,
,
.
,
R2_XORPEN R2_NOTXORPEN.
, .
: R2_XORPEN R2_NOTXORPEN?
,
R2_NOTXORPEN. ,
R2_XORPEN. ?
1 / (0 ,
1 ), . 4.4 4.5.
235
4.4. R2_XORPEN
R2_XORPEN
4.5. R2_NOTXORPEN
R2_NOTXORPEN
,
, ,
. ,
, . ,
R2_XORPEN
R2_NOTXORPEN.
RGB.
, . 4.4 4.5,
, .
( PS_SOLID).
(, PS_DOT),
:
R2_XORPEN, R2_NOTXORPEN.
.
, ( 4.4).
4.4. ElasticRect
//////////////////////////////////////////////////////////////////////
// ElasticRect.cpp
#include <windows.h>
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("Elastic Rectangle", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
236
4.
4.4 ()
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
UINT style;
static HDC hDC;
static
int x1, y1, x2, y2;
static BOOL bTracking = FALSE;
static HBRUSH hOldBrush;
static HPEN hDotPen, hOldPen;
switch (uMsg)
{
case WM_CREATE:
style = GetClassLong(hWnd, GCL_STYLE);
SetClassLong(hWnd, GCL_STYLE, style | CS_DBLCLKS);
hDotPen = CreatePen(PS_DOT, 1, RGB(0,0,0));
hDC = GetDC(hWnd);
hOldBrush = (HBRUSH)SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
break;
case WM_LBUTTONDOWN:
bTracking = TRUE;
SetROP2(hDC, R2_NOTXORPEN);
x1 = x2 = LOWORD(lParam);
y1 = y2 = HIWORD(lParam);
hOldPen = (HPEN)SelectObject(hDC, hDotPen);
Rectangle(hDC, x1, y1, x2, y2);
break;
case WM_LBUTTONUP:
if (bTracking) {
bTracking = FALSE;
SetROP2(hDC, R2_COPYPEN);
//
x2 = LOWORD(lParam);
y2 = HIWORD(lParam);
SelectObject(hDC, hOldPen);
Rectangle(hDC, x1, y1, x2, y2);
}
break;
case WM_MOUSEMOVE:
if (bTracking) {
//
Rectangle(hDC, x1, y1, x2, y2);
//
x2 = LOWORD(lParam);
y2 = HIWORD(lParam);
Rectangle(hDC, x1, y1, x2, y2);
}
237
break;
case WM_LBUTTONDBLCLK:
bTracking = FALSE;
x1 = LOWORD(lParam);
y1 = HIWORD(lParam);
Rectangle(hDC, x1, y1, x1 + 100, y1 + 100);
break;
case WM_DESTROY:
SelectObject(hDC, hOldBrush);
ReleaseDC(hWnd, hDC);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
WM_CREATE,
WM_LBUTTONDOWN WM_LBUTTONUP.
WM_CREATE
CS_DBLCLKS.
. hDotPen
PS_DOT hDC,
.
(HOLLOW_BRUSH), .
WM_LBUTTONDOWN
R2_NOTXORPEN
hDotPen. WM_MOUSEMOVE
.
WM_LBUTTONUP
R2_COPYPEN
(hOldPen).
WM_PAINT,
, Scribble,
.
ScribbleAdvanced,
.
TextViewer (. 2.2),
.
, Windows
. Windows
238
4.
SB_.
.
, ,
TextViewer, ,
.
, , ,
.
. WM_KEYDOWN,
,
WM_VSCROLL WM_HSCROLL.
.
, ,
, ,
, SB_. , ,
SB_.
Win32 API .
SendMessage,
:
LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
, ,
. SendMessage, Windows
hWnd,
. ,
Windows SendMessage .
4.5
1.
4.5. TextViewerAdv
//////////////////////////////////////////////////////////////////////
// TextViewerAdv.cpp
#include <windows.h>
#include <zmouse.h>
//
#include "KWnd.h"
#include "KDocument.h"
#define FILE_NAME "D:\\Program files\\Microsoft Visual
Studio\\VC98\\MFC\\SRC\\README.TXT"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
KDocument doc;
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
239
if (!doc.Open(FILE_NAME))
return 0;
KWnd mainWnd("Text Viewer Advanced", hInstance, nCmdShow, WndProc, NULL,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, CS_HREDRAW | CS_VREDRAW,
WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
TEXTMETRIC tm;
int cxClient=0, cyClient=0;
static int xInc, yInc;
short status;
switch (uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
GetTextMetrics(hDC, &tm);
doc.Initialize(&tm);
ReleaseDC(hWnd, hDC);
break;
case WM_SIZE:
hDC = GetDC(hWnd);
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
if (cxClient > 0)
doc.ScrollSettings(hWnd, cxClient, cyClient);
ReleaseDC(hWnd, hDC);
break;
case WM_VSCROLL:
switch(LOWORD(wParam)) {
case SB_LINEUP:
yInc = -1; break;
case SB_LINEDOWN:
yInc = 1; break;
case SB_PAGEUP:
yInc = -(int)doc.vsi.nPage; break;
case SB_PAGEDOWN:
yInc = (int)doc.vsi.nPage; break;
case SB_THUMBTRACK:
yInc = HIWORD(wParam) - doc.vsi.nPos;
case SB_TOP:
yInc = -doc.vsi.nPos; break;
case SB_BOTTOM:
break;
240
4.
4.5 ()
yInc = doc.vsi.nMax - doc.vsi.nPos;
default:
yInc = 0;
}
doc.UpdateVscroll(hWnd, yInc);
break;
break;
case WM_HSCROLL:
switch(LOWORD(wParam)) {
case SB_LINELEFT:
xInc = -1; break;
case SB_LINERIGHT:
xInc = 1; break;
case SB_PAGELEFT:
xInc = -0.8 * (int)doc.hsi.nPage; break;
case SB_PAGERIGHT:
xInc = 0.8 * (int)doc.hsi.nPage; break;
case SB_THUMBTRACK:
xInc = HIWORD(wParam) - doc.hsi.nPos; break;
case SB_TOP:
xInc = -doc.hsi.nPos; break;
case SB_BOTTOM:
xInc = doc.hsi.nMax - doc.hsi.nPos; break;
default:
xInc = 0;
}
doc.UpdateHscroll(hWnd, xInc);
break;
case WM_MOUSEWHEEL:
if (LOWORD(wParam) & MK_SHIFT) {
xInc = -3 * (short)HIWORD(wParam) / WHEEL_DELTA;
doc.UpdateHscroll(hWnd, xInc);
}
else {
yInc = -3 * (short)HIWORD(wParam) / WHEEL_DELTA;
doc.UpdateVscroll(hWnd, yInc);
}
break;
case WM_KEYDOWN:
switch (wParam) {
case VK_UP:
SendMessage(hWnd,
break;
case VK_DOWN: SendMessage(hWnd,
break;
case VK_LEFT: SendMessage(hWnd,
break;
case VK_RIGHT: SendMessage(hWnd,
break;
case VK_PRIOR: SendMessage(hWnd,
break;
case VK_NEXT: SendMessage(hWnd,
break;
case VK_HOME:
status = GetKeyState(VK_CONTROL);
241
WM_MOUSEWHEEL
WM_KEYDOWN.
short (short)
HIWORD(wParam) WM_MOUSEWHEEL.
, .
WM_MOUSEWHEEL
Shift. ,
, .
TextViewer TextViewerAdv.
242
5. Windows-
Windows-
Windows.
, , , , ,
, .
(
) . , 1.1
,
.
(resource script), ASCII .rc.
,
,
,
.
,
.
MS Visual Studio 6.0
.
FileSave.
Visual Studio
script1.rc.
, (,
MyApp.rc).
( rc.exe
).
.res.
.obj .lib. Visual Studio
Build .
Windows
.
.
243
. MS Visual Studio 6.0
:
, , ,
;
, .
, .
, , ,
, 1.
. 6, 7 8
, .
, Windows
, . ,
,
. , Windows
Start (), ,
, , Windows
Explorer . ,
.
Windows
32 32 . Windows 95,
: 16 16 , 32 32
48 48 .
16,
256 .
, Start. ,
1
(MSDN) , .
, .
, ,
. , .
244
5. Windows-
, . ,
Windows Explorer,
.
(48 48) ,
Windows.
,
.
:
.
Visual Studio,
, .ico,
:
32 32, 16 ( ).
32 32, 256 .
48 48, 256 .
32 32, .
16 16, 16 .
,
. Windows
, .
.
.
,
.
.
.
. ,
Win32 Application Russia.
Russia.cpp, ,
5.1.
5.1. Russia ( )
//////////////////////////////////////////////////////////////////////
// Russia.cpp
#include <windows.h>
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("Russia today", hInstance, nCmdShow, WndProc, NULL, 0, 0,
400, 300);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
245
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
, Workspace :
ClassView FileView. FileView
, .
246
5. Windows-
:
1. . Visual Studio
InsertResource. Insert
Resource (. 5.2).
Icon New.
Script1 IDI_ICON1
(. 5.3).
247
.
Graphics , Colors
. ,
Graphics Colors.
2. . Device
Standard (3232).
New Device Image.
, New Icon Image Target device (. 5.4).
,
OK, Device.
Russia.cpp .
Small(1616)
OK.
.
3. .
: Script1 IDI_ICON1 (Icon).
.
Script1, .
, ,
(. . 5).
.
IDI_ICON1.
,
IDI_ICON2, IDI_ICON3 . .
.
, .
,
IDI_TRICOLOUR.
. Icon Properties
(. 5.5).
General ID
File name ,
.
IDI_TRICOLOUR tricol.ico.
248
5. Windows-
, Palette.
16 .
, Colors.
256 , 256 ,
.
Icon Properties, .
Script1
IDI_TRICOLOUR.
4. .
(16 16). , . 5.3, ,
(darkcyan) .
1.
Graphics,
. Colors.
MS Paint,
.
. 5.6.
. 5.6.
.
,
. 1 2.
1
,
.
Russia ,
(www.piter.com), .
249
(3232),
Device.
.
Russia,
(. 5.7).
. 5.7.
, 256
, Palette Icon Properties
(. . 5.5).
5. .
Visual Studio FileSave.
,
.
,
Save As ( ). File Name ( )
Script1.rc. Script1 ,
Russia, Save ().
Russia.rc IDI_TRICOLOUR.
.
Workspace Resource Files
Add Files to Folder.
Insert Files .
Russia.rc, Visual
Studio , . 5.8.
, FileView.
Resource Files : Russia.rc
tricol.ico. , Workspace
ResourceView. ,
, Icon c
IDI_TRICOLOUR.
250
5. Windows-
6. resource.h (
). ,
resource.h,
. ,
. Workspace
Header Files
Add Files to Folder. Insert
Files resource.h.
resource.h , ,
. (DLL), , .
11.
.
, ,
.
.
, .
251
, ,
AnyIcon.ico.
AnyIcon.ico .
:
Visual Studio InsertResource.
Insert Resource Icon
Import.
Import Resource ,
, AnyIcon.ico.
.
. 3
.
, . 5 6 .
.
, , .
,
.
Workspace ResourceView
.
, ,
, , , . 5.8.
.
,
FileSave.
,
. Visual Studio FileOpen.
Open (),
. 5.9.
,
( Russia). ,
. Open
as Text.
( Russia.rc). Visual
Studio .
252
5. Windows-
. 5.9. Open
Russia.rc,
:
IDI_TRICOLOUR
ICON
DISCARDABLE
"tricol.ico"
.
.
, .
:
_
DISCARDABLE
_ Windows C
, . _
ASCII
, Windows .
_ C,
( ) .
, C Windows,
Visual Studio
. ,
resource.h Russia, :
#define
IDI_TRICOLOUR
101
:
101
ICON
DISCARDABLE
"tricol.ico"
, , Russia.rc,
IDI_TRICOLOUR tricol.ico,
: .
DISCARDABLE ()
Windows,
, . Win32
.
253
, HICON,
LoadIcon LoadImage.
LoadIcon 1.
. LoadIcon
(.exe),
hInstance:
HICON LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName);
, ,
. ,
, , _
.
MAKEINTRESOURCE (make an integer into resource string),
winuser.h :
#define MAKEINTRESOURCE(i) (LPSTR)((DWORD)((WORD)(i)))
, 16
. Windows ,
LoadIcon , .
, Russia
:
LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TRICOLOUR));
.
hinst NULL fuLoad LR_LOADFROMFILE,
lpszName
LoadIcon.
254
5. Windows-
LR_DEFAULTCOLOR
. ,
LR_CREATEDIBSECTION
uType IMAGE_BITMAP,
DIB-
LR_DEFAULTSIZE
LR_LOADFROMFILE
LR_MONOCHROME
Russia.
, hIcon
hIconSm .
KWnd,
KWnd (.
KWnd.cpp).
SetClassLong.
WM_CREATE, ,
.
Russia.cpp 5.2.
255
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HINSTANCE hInst;
HICON hIcon;
//
HICON hIconSm; //
switch (uMsg)
{
case WM_CREATE:
hInst = GetModuleHandle(NULL);
hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_TRICOLOUR));
hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_TRICOLOUR),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
SetClassLong(hWnd, GCL_HICON, (LONG)hIcon);
SetClassLong(hWnd, GCL_HICONSM, (LONG)hIconSm);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
WM_CREATE LoadIcon
LoadImage
. hInst,
, GetModuleHandle.
256
5. Windows-
hIcon hIconSm
SetClassLong, (hIcon, hIconSm)
mainWnd.wc .
:
#include "resource.h"
IDI_TRICOLOUR .
(. 5.10).
32 32 ,
() . .
(hotspot).
,
.
, ,
.
,
, , Russia.
, .
,
IDC_CROSS.
, ,
, .
,
, . ,
IDC_UP IDC_DOWN.
.
Insert Resource Icon Cursor.
.
, ,
. , IDC_UP
. 5.11.
257
. 5.11. IDC_UP
,
, Set Hotspot,
.
(0, 0).
.
, Set Hotspot,
,
. .
Hot spot: 15, 0.
IDC_DOWN.
(. 5.12).
. 5.12. IDC_DOWN
,
FileSave. Russia.rc ,
:
IDC_UP
IDC_DOWN
CURSOR
CURSOR
DISCARDABLE
DISCARDABLE
"up.cur"
"down.cur"
, .
( HCURSOR)
LoadCursor,
LoadIcon.
258
5. Windows-
: hCursor
( IDC_CROSS), hCursorUp
(IDC_UP) hCursorDown (IDC_DOWN).
hCursor .
,
:
SetClassLong(hWnd, GCL_HCURSOR, (LONG)hCursor);
SetCursor:
HCURSOR SetCursor(HCURSOR hCursor);
,
. .
WM_MOUSEMOVE. lParam
x y,
.
.
Russia.cpp 5.3.
5.3. Russia (2- )
//////////////////////////////////////////////////////////////////////
// Russia.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("Russia today", hInstance, nCmdShow, WndProc, NULL, 0, 0,
400, 300);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HINSTANCE hInst;
HICON hIcon, hIconSm;
static HCURSOR hCursor, hCursorUp, hCursorDown;
static int xPos, yPos; //
static int wClient, hClient; //
HDC hDC;
PAINTSTRUCT ps;
char text[100];
RECT rect;
259
wClient hClient
WM_SIZE. hClient
WM_MOUSEMOVE,
, , .
,
, . 5.13.
260
5. Windows-
. 5.13. Russia c ,
, ,
InvalidateRect WM_MOUSEMOVE:
InvalidateRect(hWnd, &rect, TRUE);
, ,
, .
WM_PAINT. ,
DrawText .
,
, ,
. Windows ,
BeginPaint, .
WM_PAINT InvalidateRect
, TRUE.
InvalidateRect. ,
, .
NULL, .
,
.
.
3 Windows
.
, DDB . ,
.
.
, .
, Windows
,
, , ,
.
261
.
, Windows
.
12.1 ( 12).
. Insert Resource
Icon Bitmap.
. ,
.
( ), Bitmap
Properties (. 5.14) ,
, 16 256 .
,
,
, .
.
.
HBITMAP , LoadBitmap:
HBITMAP LoadBitmap(
HINSTANCE hInstance,
LPCTSTR lpBitmapName
);
//
//
, LoadIcon.
Win32 DIB
. LoadBitmap , ,
DIB, DDB,
, DDB.
BitBlt
StretchBlt .
3.
Russia.
.
MS Paint. 400 280
,
Russia today (. 5.15).
262
5. Windows-
RusFlag.bmp, 256
. Russia1.
,
RusFlag.bmp IDB_RUSFLAG.
Russia.rc ,
:
IDB_RUSFLAG
BITMAP
DISCARDABLE
"RusFlag.bmp"
.
.
static HBITMAP hBmpRusFlag;
HDC hMemDC;
static BITMAP bm;
//
//
//
WM_CREATE
hBmpRusFlag = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_RUSFLAG));
GetObject(hBmpRusFlag, sizeof(bm), (LPSTR)&bm);
WM_PAINT BeginPaint
:
hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hBmpRusFlag);
BitBlt(hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
,
. 5.16.
1
,
, (www.piter.com).
263
. 5.16. Russia.
,
.
. (&rect) InvalidateRect
NULL . ,
.
,
, (userdefined resource),
,
.
: , .
, proghelp.txt,
.
, :
HELPTEXT
TEXT
DISCARDABLE
proghelp.txt
(HELPTEXT) (TEXT)
. ,
.
,
WM_CREATE, ,
proghelp.txt.
:
.
, ,
.
, Visual Studio
, .
264
5. Windows-
:
_
DISCARDABLE
, .
, .
, ,
FindResource, LoadResource LockResource.
FindResource .
:
HRSRC FindResource(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType);
hModule
, . hModule NULL, Windows
, .
lpName , , , .
#,
. lpType .
, .
,
LoadResource. FindResource NULL.
LoadResource , FindResource,
.
:
HGLOBAL LoadResource(HMODULE hModule, HRSRC hResInfo);
hResInfo
, FindResource.
, LoadResource, ,
, MSDN
, LockResource:
LPVOID LockResource(HGLOBAL hResData);
.
hResData , .
, LoadResource.
LockResource
, NULL.
,
.
proghelp.txt,
,
:
HGLOBAL hResource = LoadResource(hInstance,
FindResource(hInstance, "HELPTEXT", "TEXT"));
char* pHelpText = (char*) LockResource(hResource);
265
, ,
.
, . ,
,
.
, ,
.
Win32 API ,
WAVE (waveform audio file fomat).
.wav. 8 16
. WAVE
, ,
. .wav,
,
.
PlaySound,
:
BOOL PlaySound(
LPCSTR pszSound,
HMODULE hmod,
DWORD fdwSound
);
// ,
//
//
,
. PlaySound NULL,
.
. ,
NULL.
. . 5.2
.
5.2. fdwSound
SND_FILENAME
pszSound
SND_RESOURCE
pszSound
SND_SYNC
. PlaySound
SND_ASYNC
. PlaySound
.
PlaySound, pszSound NULL
266
5. Windows-
5.2. ()
SND_LOOP
,
PlaySound, pszSound NULL.
SND_ASYNC
SND_NODEFAULT
. ,
PlaySound ,
SND_PURGE
pszSound NULL,
. NULL,
SND_NOWAIT
PlaySound Windows.
Visual Studio,
winmm.lib1.
,
PlaySound . ,
.wav exe
. ,
.
. ,
,
! ,
, , exe
.
PlaySound
. ,
FindResource, LoadResource
LockResource.
PlaySound.
PlaySound
Russia.
, .
, RussiaToday,
, ,
. ,
.
RussiaToday.rc
MY_SOUND
WAVE
DISCARDABLE
"RusHymn.wav"
RusHymn.wav
2.
1
267
5.4.
5.4. RussiaToday
//////////////////////////////////////////////////////////////////////
// RussiaToday.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "resource.h"
char szSoundName[] = "MY_SOUND";
//
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HINSTANCE hInst;
HICON hIcon, hIconSm;
HDC hDC;
PAINTSTRUCT ps;
static HBITMAP hBmpRusFlag;
HDC hMemDC;
static BITMAP bm;
switch (uMsg)
{
case WM_CREATE:
hInst = GetModuleHandle(NULL);
hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_TRICOLOUR));
hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_TRICOLOUR),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
SetClassLong(hWnd, GCL_HICON, (LONG)hIcon);
SetClassLong(hWnd, GCL_HICONSM, (LONG)hIconSm);
hBmpRusFlag = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_RUSFLAG));
GetObject(hBmpRusFlag, sizeof(bm), (LPSTR)&bm);
//
PlaySound (szSoundName, hInst, SND_RESOURCE | SND_ASYNC);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hBmpRusFlag);
268
5. Windows-
5.4. ()
BitBlt(hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
RussiaToday ,
, . 5.16,
, .
!
, , ,
.
! Win32 API WAVE
, MP3!
ShellExecute:
ShellExecute(hWnd, "open", "MySound.mp3", NULL, NULL, SW_SHOW);
ShellExecute
, .mp3.
, WinAmp, ,
Windows Media Player.
MySound.mp3.
,
.
:
STRINGTABLE DISCARDABLE
BEGIN
IDS_STRING1
" "
IDS_STRING2
" "
IDS_STRING3
" "
END
.
.
Windows . ,
269
,
, .
? ,
:
;
(tooltip) (status bar) .
.
,
,
.
.
Tooltip
. 8.
:
1. Visual Studio InsertResource.
Insert Resource String Table
New.
, . 5.17.
. 5.17.
2. .
String Properties, . 5.18.
. 5.18.
ID
Caption. .
270
5. Windows-
3. , . 2, ,
.
4. FileSave.
.
255 .
C, \t.
\011 (
), \012 ( ) \015 ( ).
DrawText MessageBox.
LoadString
szBuffer:
LoadString(hInstance, id, szBuffer, iMaxLength);
id ,
iMaxLength .
,
.
StringTable
. :
IDS_FILENOTFOUND
IDS_FILETOOBIG
IDS_FILEREADONLY
%s
%s
%s
StringTable.rc
:
STRINGTABLE DISCARDABLE
BEGIN
IDS_FILENOTFOUND
IDS_FILETOOBIG
IDS_FILEREADONLY
END
" %s ."
" %s ."
" %s ."
271
{
MSG msg;
KWnd mainWnd("StringTable", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
StatusFileMsg(hWnd, IDS_FILEREADONLY, "File_1");
StatusFileMsg(hWnd, IDS_FILETOOBIG, "File_2");
StatusFileMsg(hWnd, IDS_FILENOTFOUND, "File_3");
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
int StatusFileMsg(HWND hwnd, int status, char* fileName)
{
HINSTANCE hInst;
char szFormat[80];
char szBuffer[200];
hInst = GetModuleHandle(NULL);
LoadString(hInst, status, szFormat, 80);
sprintf(szBuffer, szFormat, fileName);
return MessageBox(hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION);
}
//////////////////////////////////////////////////////////////////////
StatusFileMsg,
. fileName,
status. ,
, .
StatusFileMsg .
,
.
8 ,
. ToolBar ( 8.1)
StatusBar ( 8.5).
272
6.
Windows
.
(menu bar), .
, Microsoft Visual Studio 6.0 ,
File, Edit, View, Insert , . 6.1.
Windows .
.
.
, ,
(main menu), .
.
,
.
, ,
.
, .
.
.
273
,
. .
(hotkey) .
:
;
.
()
. ,
, .
.
,
.
. ,
Windows , .
.
Windows .
, Windows WM_COMMAND,
. ,
Windows ,
(popup menu).
. . 6.2 File
Visual Studio.
,
, .
(. New).
274
6.
,
.
.
File. New, Open
. ,
.
,
.
,
, . , ,
,
.
Recent Files Recent Workspaces .
, .
, , Windows
, .
.
Ctrl+N, Ctrl+O
.
, .
, , ,
,
.
. ,
.
, Windows
.
, Alt F10,
.
:
1. /
Enter.
2. ,
.
,
/.
,
, , ,
. .
275
(enabled), (disabled)
(grayed).
.
, WM_COMMAND
, .
.
, . ,
Enter .
.
, , .
, , ,
.
.
, Windows ,
.
. ,
,
.
,
? MSDN ,
,
.
EnableMenuItem.
(check box).
.
.
, .
,
.
(radio
button). , , .
,
, .
.
. 6.3 MenuDemo1,
, .
RGB .
.
: , , .
.
276
6.
. 6.3. - - Color
CheckMenuItem.
CheckMenuRadioItem.
,
, .
.
, Windows
, . ,
.
SetMenuDefaultItem.
:
, ;
CreateMenu AppendMenu;
,
LoadMenuIndirect.
.
.
:
_ MENU DISCARDABLE
BEGIN
0-
1-
...
(n-1)-
END
277
Windows C
, .
(. 5).
i (i = 0,1,..., n 1) .
:
POPUP _ [, ]
BEGIN
0-
1-
...
(n-1)-
END
, ( )
.
:
MENUITEM _ [, ]
&,
.
SEPARATOR, ,
.
,
.
Visual Studio InsertResource.
Insert Resource Menu
New.
(. 6.4).
. 6.4.
IDR_MENU1. resource.h
. ,
Menu
Properties ID. ,
IDR_MENU1,
, .
. .
278
6.
,
Menu Item Properties (. 6.5),
.
. 6.1.
6.1.
ID
Caption
( &,
)
Separator
Checked
Pop-up
, .
Grayed
( Inactive)
Inactive
( Grayed)
Break
: None
; Column ,
; Bar
. 6.5,
( Pop-up ).
, Pop-up
. ID
(. 6.6).
279
- , ID_. ,
. ,
MenuDemo1 ID_RECTANGLE,
ID_RHOMB, ID_ELLIPSE. 7 DlgDemo2 ,
.
, .
.
,
. , ,
, .
,
i .
i -
1. .
2.
Menu Item Properties.
3. , (i + 1) ,
:
Pop-up;
. ,
&;
(i + 1)
, i i + 1.
4. ,
:
Pop-up;
, &;
280
6.
5. ,
:
Pop-up;
Separator;
6. .
, 3
. .
. ,
3 .
, , 6 ,
. ,
,
. , , .
,
i .
.
1.
i , i .
2.
, .
1.
. ,
. .
lpszMenuName
WNDCLASSEX ,
.
(, IDR_MENU1), MAKEINTRESOURCE
, lpszMenuName.
1
. 5, .
281
KWnd,
MAKEINTRESOURCE(IDR_MENU1)
menuName KWnd ( ,
, 6.1).
, 1,
wc WNDCLASSEX, ,
. ? ,
CreateWindow hMenu
NULL. KWnd.
,
, .
LoadMenu, :
HMENU LoadMenu(HINSTANCE hInstance, LPCTSTR lpMenuName);
hMenu, LoadMenu,
hMenu CreateWindow.
,
SetMenu:
BOOL SetMenu(HWND hWnd, HMENU hMenu);
, LoadMenu.
, .
. Win32 API
.
:
AppendMenu ;
DeleteMenu ;
InsertMenu ;
RemoveMenu .
, DeleteMenu RemoveMenu,
. DeleteMenu
, RemoveMenu .
,
, ,
. SetMenuItemInfo
.
, Windows,
C++.
282
6.
,
:
CheckMenuItem ;
CheckMenuRadioItem ;
EnableMenuItem ;
ModifyMenu .
.
CheckMenuItem
,
:
DWORD CheckMenuItem (
HMENU hmenu,
//
UINT uIDCheckItem, //
UINT uCheck
//
);
, ,
.
, .
.
, uCheck,
. : MF_BYCOMMAND
MF_BYPOSITION. : MF_CHECKED
MF_UNCHECKED. . 6.2.
6.2. uCheck
MF_BYCOMMAND
MF_BYPOSITION
MF_CHECKED
uIDCheckItem
uIDCheckItem
MF_UNCHECKED
CheckMenuItem , CheckMenuRadioItem,
.
.
MF_BYCOMMAND, uIDCheckItem
. ,
, .
, .
CheckMenuRadioItem
:
283
BOOL CheckMenuRadioItem (
HMENU hmenu, //
UINT idFirst, //
UINT idLast, //
UINT idCheck, //
UINT uFlags
// idFirst, idLast idCheck
);
uFlags MF_BYCOMMAND,
. uFlags
MF_BYPOSITION, .
, , resource.h . CheckMenuRadioItem
.
EnableMenuItem
.
:
BOOL EnableMenuItem (
HMENU hMenu,
//
UINT uIDEnableItem, //
UINT uEnable
//
);
CheckMenuItem, uEnable
MF_BYCOMMAND MF_BYPOSITION, :
MF_ENABLED ( ), MF_DISABLED ( ) MF_GRAYED (
).
, DrawMenuBar
.
ModifyMenu
:
BOOL ModifyMenu (
HMENU hMnu,
UINT uPosition,
UINT uFlags,
UINT_PTR uIDNewItem,
LPCTSTR lpNewItem
);
//
//
//
//
//
284
6.
6.3. , lpNewItem
lpNewItem
MF_STRING
C-.
MF_BITMAP
.
,
MF_OWNERDRAW
,
OwnerDraw
,
. , Win32 API ,
,
.
, hWnd,
GetMenu:
HMENU GetMenu(HWND hWnd);
NULL, hWnd .
.
GetSubMenu:
HMENU GetSubMenu (
HMENU hMenu, //
int nPos
// -
);
nPos
. nPos ,
, NULL.
Windows WM_COMMAND
, . ,
, .
WM_SYSCOMMAND.
WM_INITMENU
WM_INITMENUPOPUP.
.
, .
WM_MENUCHAR ,
,
.
.
WM_MENUSELECT.
c WM_COMMAND,
, .
285
,
.
, WM_COMMAND,
DefWindowProc.
WM_COMMAND
:
LRESULT CALLBACK WndProc (
HWND hWnd,
//
UINT uMsg,
// WM_COMMAND
WPARAM wParam, //
LPARAM lParam // 0
);
WM_COMMAND
, , (,
, . .).
lParam.
wParam (. 6.4).
6.4. wParam lParam
wParam
wParam
lParam
(
)
(HWND)
WM_COMMAND
switch. , MenuDemo1,
, File
:
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_OPEN:
MessageBox(hWnd, " 'Open'", " File", MB_OK);
break;
case IDM_CLOSE:
MessageBox(hWnd, " 'Close'", " File", MB_OK);
break;
case IDM_SAVE:
MessageBox(hWnd, " 'Save'", " File", MB_OK);
break;
case IDM_EXIT:
SendMessage(hWnd, WM_DESTROY, 0, 0);
break;
}
// ...
286
6.
, IDM_OPEN,
IDM_CLOSE IDM_SAVE
MessageBox. IDM_EXIT ,
.
MenuDemo1
MenuDemo1.
MenuDemo1 . 6.3.
, .
.
Red, Green, Blue ,
: Dark ( ), Medium ( ), Light
( ).
,
.
, .
File,
.
.
MenuDemo1.
KWnd.h KWnd.cpp 1.2 .
MenuDemo1.rc.
, . 6.5.
6.5. (0- )
&File
&View
&Draw shape
&Increase!
IDM_RESIZE
0
1
2
3
&About
IDM_ABOUT
Increase .
, ,
, .
File , . 6.6.
6.6. File (1- )
&Open
&Close
&Save
SEPARATOR
IDM_OPEN
IDM_CLOSE
IDM_SAVE
E&xit
IDM_EXIT
287
MenuDemo1
View , . 6.7.
6.7. View (1- )
&Show shape
IDM_SHOW_SHAPE
&Hide shape
IDM_HIDE_SHAPE
&Shape
&Color
Shape , . 6.9.
6.9. Shape (2- )
&Rectangle
Rhom&b
&Ellipse
ID_RECTANGLE
ID_RHOMB
ID_ELLIPSE
Color , . 6.10.
6.10. Color (2- )
&Red
&Green
&Blue
&Dark
&Medium
&Light
SEPARATOR
ID_RED
ID_GREEN
ID_BLUE
ID_DARK
ID_MEDIUM
ID_LIGHT
MenuDemo1.cpp
, 6.11.
6.1. MenuDemo1
//////////////////////////////////////////////////////////////////////
// MenuDemo1.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "resource.h"
#define W
#define H
1
200
140
//
//
, , http://
www.piter.com.
288
6.
6.1 ()
enum ShapeSize { MAX, MIN };
typedef struct {
int id_shape;
BOOL fRed;
BOOL fGreen;
BOOL fBlue;
int id_bright;
} ShapeData;
//
//
//
//
//
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
static HMENU hMenu; //
int x0, y0, x1, y1, x2, y2;
POINT pt[4];
static ShapeSize shapeSize = MIN;
static BOOL bShow = TRUE;
static HBRUSH hBrush, hOldBrush;
char* itemResizeName[2] = { "Decrease!", "Increase!"};
int intensity[3] = { 85, 170, 255 }; // RGB-
int brightness;
static ShapeData shapeData;
switch (uMsg)
{
case WM_CREATE:
hMenu = GetMenu(hWnd);
// IDM_OPEN - ,
SetMenuDefaultItem(GetSubMenu(hMenu, 0), IDM_OPEN, FALSE);
//
CheckMenuRadioItem(GetSubMenu(hMenu, 1), IDM_SHOW_SHAPE,
IDM_HIDE_SHAPE, IDM_SHOW_SHAPE, MF_BYCOMMAND);
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_RECTANGLE,
ID_ELLIPSE, ID_RECTANGLE, MF_BYCOMMAND);
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_DARK,
ID_LIGHT, ID_DARK, MF_BYCOMMAND);
shapeData.id_shape = ID_RECTANGLE;
MenuDemo1
289
shapeData.id_bright = ID_DARK;
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_OPEN:
MessageBox(hWnd, " 'Open'", " File", MB_OK);
break;
case IDM_CLOSE:
MessageBox(hWnd, " 'Close'", " File", MB_OK);
break;
case IDM_SAVE:
MessageBox(hWnd, " 'Save'", " File", MB_OK);
break;
case IDM_EXIT:
SendMessage(hWnd, WM_DESTROY, 0, 0);
break;
case IDM_SHOW_SHAPE:
bShow = TRUE;
CheckMenuRadioItem(GetSubMenu(hMenu, 1), IDM_SHOW_SHAPE,
IDM_HIDE_SHAPE, LOWORD(wParam), MF_BYCOMMAND);
EnableMenuItem(hMenu, IDM_RESIZE, MF_BYCOMMAND | MFS_ENABLED);
DrawMenuBar(hWnd);
break;
case IDM_HIDE_SHAPE:
bShow = FALSE;
CheckMenuRadioItem(GetSubMenu(hMenu, 1), IDM_SHOW_SHAPE,
IDM_HIDE_SHAPE, LOWORD(wParam), MF_BYCOMMAND);
EnableMenuItem(hMenu, IDM_RESIZE, MF_BYCOMMAND | MFS_GRAYED);
DrawMenuBar(hWnd);
break;
case ID_RECTANGLE:
shapeData.id_shape = ID_RECTANGLE;
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_RECTANGLE,
ID_ELLIPSE, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_RHOMB:
shapeData.id_shape = ID_RHOMB;
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_RECTANGLE,
ID_ELLIPSE, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_ELLIPSE:
shapeData.id_shape = ID_ELLIPSE;
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_RECTANGLE,
ID_ELLIPSE, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_RED:
shapeData.fRed = ~shapeData.fRed;
CheckMenuItem(GetSubMenu(hMenu, 2), ID_RED,
MF_BYCOMMAND | shapeData.fRed? MF_CHECKED : MF_UNCHECKED);
break;
case ID_GREEN:
shapeData.fGreen = ~shapeData.fGreen;
290
6.
6.1 ()
CheckMenuItem(GetSubMenu(hMenu, 2), ID_GREEN,
MF_BYCOMMAND | shapeData.fGreen? MF_CHECKED : MF_UNCHECKED);
break;
case ID_BLUE:
shapeData.fBlue = ~shapeData.fBlue;
CheckMenuItem(GetSubMenu(hMenu, 2), ID_BLUE,
MF_BYCOMMAND | shapeData.fBlue? MF_CHECKED : MF_UNCHECKED);
break;
case ID_DARK:
shapeData.id_bright = ID_DARK;
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_DARK,
ID_LIGHT, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_MEDIUM:
shapeData.id_bright = ID_MEDIUM;
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_DARK,
ID_LIGHT, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_LIGHT:
shapeData.id_bright = ID_LIGHT;
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_DARK,
ID_LIGHT, LOWORD(wParam), MF_BYCOMMAND);
break;
case IDM_RESIZE:
shapeSize = (shapeSize == MIN)? MAX : MIN;
ModifyMenu(hMenu, IDM_RESIZE, MF_BYCOMMAND, IDM_RESIZE,
itemResizeName[shapeSize]);
DrawMenuBar(hWnd);
break;
case IDM_ABOUT:
MessageBox(hWnd,
"MenuDemo1\nVersion 1.0\nCopyright: Finesoft Corporation, 2005.",
"About MenuDemo1", MB_OK);
break;
default:
break;
}
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
brightness = intensity[shapeData.id_bright - ID_DARK];
if (bShow) {
hBrush = CreateSolidBrush(RGB(
shapeData.fRed? brightness : 0,
shapeData.fGreen? brightness : 0,
shapeData.fBlue? brightness : 0));
hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
// (x0, y0)
GetClientRect(hWnd, &rect);
291
MenuDemo1
x0
y0
//
if
= rect.right / 2;
= rect.bottom / 2;
(shapeSize == MIN) {
x1 = x0 - W/2;
y1 = y0 - H/2;
x2 = x0 + W/2;
y2 = y0 + H/2;
}
else {
x1 = y1 = 0;
x2 = rect.right; y2 =
}
//
pt[0].x = (x1 + x2) / 2;
pt[1].x = x2;
pt[2].x = (x1 + x2) / 2;
pt[3].x = x1;
rect.bottom;
pt[0].y
pt[1].y
pt[2].y
pt[3].y
= y1;
= (y1 + y2) / 2;
= y2;
= (y1 + y2) / 2;
switch (shapeData.id_shape) {
case ID_RECTANGLE:
Rectangle(hDC, x1, y1, x2, y2);
break;
case ID_RHOMB:
Polygon(hDC, pt, 4);
break;
case ID_ELLIPSE:
Ellipse(hDC, x1, y1, x2, y2);
break;
}
DeleteObject(SelectObject(hDC, hOldBrush));
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
.
, , MenuDemo1.rc
IDR_MENU1, mainWnd
KWnd:
KWnd mainWnd("MenuDemo1", hInstance, nCmdShow, WndProc,MAKEINTRESOURCE(IDR_MENU1),,
100, 100, 400, 300);
shapeData
ShapeData.
WM_CREATE
hMenu , SetMenuDefaultItem
292
6.
Open
File. File,
, GetSubMenu(hMenu, 0).
CheckMenuRadioItem
, :
View
IDM_SHOW_SHAPE
IDM_HIDE_SHAPE
Shape
ID_RECTANGLE
IM_ELLIPSE
Color
ID_DARK
ID_LIGHT
,
CheckMenuRadioItem. ,
bShow, shapeData.id_shape shapeData.id_bright.
.
, Color, ,
CheckMenuItem,
WM_COMMAND wParam,
IDM_RED, IDM_GREEN IDM_BLUE.
Increase! c IDM_RESIZE
, shapeSize MIN MAX
.
.
, WM_COMMAND wParam,
IDM_RESIZE, Increase Decrease .
ModifyMenu. ,
, itemResizeName.
ModifyMenu DrawMenuBar,
.
Hide shape
View, .
, IDM_RESIZE
. WM_COMMAND wParam,
IDM_HIDE_SHAPE, EnableMenuItem,
MFS_GRAYED.
. WM_COMMAND wParam,
IDM_SHOW_SHAPE, EnableMenuItem MFS_ENABLED,
IDM_RESIZE .
WM_COMMAND wParam, IDM_ABOUT,
MessageBox,
.
WM_COMMAND
InvalidateRect,
.
,
.
293
, (shortcut menu),
.
, .
, .
,
, ,
.
.
,
.
,
,
. .
GetSubMenu.
( 1 ) , .
,
, IDR_MENU_MYCONTEXT.
WM_CREATE LoadMenu GetSubMenu:
HMENU hMenuMyContext;
hMenuMyContext = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU_MYCONTEXT));
hMenuMyContext = GetSubMenu(hMenuMyContext, 0);
LoadMenu ,
IDR_MENU_MYCONTEXT.
, .
,
hMenuMyContext
GetSubMenu.
hMenuMyContext Track PopupMenuEx, .
, Windows
WM_RBUTTONDOWN,
1 . , Windows
WM_CONTEXTMENU, (screen coordinates)
1
294
6.
. ,
, TrackPopupMenuEx:
BOOL TrackPopupMenuEx (
HMENU hmenu,
//
UINT fuFlags,
//
int x,
//
int y,
//
HWND hwnd,
//
LPTPMPARAMS lptpm //
);
,
(x, y), ,
.
, .
(x, y).
x y
.
lParam WM_RBUTTONDOWN WM_CONTEXTMENU.
, WM_RBUTTONDOWN
,
ClientToScreen.
hwnd , .
. lptpm
, .
NULL.
,
.
, ,
,
.
.
MenuDemo2
MenuDemo2 , MenuDemo1,
. MenuDemo2
, MenuDemo1, Draw shape.
Shape Color Draw shape
.
,
, . ,
,
.
MenuDemo2.
MenuDemo1 MenuDemo2 .cpp, .h .rc,
MenuDemo1 MenuDemo2.
.
295
recource.h
// Used by MenuDemo1.rc
:
// Used by MenuDemo2.rc
Workspace ResourceView,
Menu IDR_MENU1
.
Draw shape,
Delete. Visual Studio ,
(. 6.7).
OK .
,
.
IDR_MENU_SHAPE IDR_MENU_COLOR .
IDR_MENU_SHAPE
shape, shape ,
. 6.9. IDR_MENU_COLOR
color. color ,
. 6.10.
MenuDemo2.cpp 6.2.
6.2. MenuDemo2
//////////////////////////////////////////////////////////////////////
// MenuDemo2.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "resource.h"
#define W 200
//
#define H 140
//
enum ShapeSize { MAX, MIN };
typedef struct {
int id_shape;
BOOL fRed;
BOOL fGreen;
BOOL fBlue;
int id_bright;
} ShapeData;
//
//
//
//
//
296
6.
6.2 ()
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("MenuDemo2", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
static HMENU hMenu;
//
static HMENU hMenuShape; // 1-
static HMENU hMenuColor; // 2-
POINT point, ptInClient;
int x0, y0, x1, y1, x2, y2;
POINT pt[4];
static ShapeSize shapeSize = MIN;
static BOOL bShow = TRUE;
static HBRUSH hBrush, hOldBrush;
char* itemResizeName[2] = { "Decrease!", "Increase!"};
int intensity[3] = { 85, 170, 255 }; // RGB-
int brightness;
static ShapeData shapeData;
switch (uMsg)
{
case WM_CREATE:
hMenu = GetMenu(hWnd);
hMenuShape = LoadMenu(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDR_MENU_SHAPE));
hMenuShape = GetSubMenu(hMenuShape, 0);
hMenuColor = LoadMenu(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDR_MENU_COLOR));
hMenuColor = GetSubMenu(hMenuColor, 0);
// IDM_OPEN - ,
SetMenuDefaultItem(GetSubMenu(hMenu, 0), IDM_OPEN, FALSE);
//
CheckMenuRadioItem(GetSubMenu(hMenu, 1), IDM_SHOW_SHAPE,
IDM_HIDE_SHAPE, IDM_SHOW_SHAPE, MF_BYCOMMAND);
CheckMenuRadioItem(hMenuShape, ID_RECTANGLE,
ID_ELLIPSE, ID_RECTANGLE, MF_BYCOMMAND);
CheckMenuRadioItem(hMenuColor, ID_DARK,
ID_LIGHT, ID_DARK, MF_BYCOMMAND);
shapeData.id_shape = ID_RECTANGLE;
297
shapeData.id_bright = ID_DARK;
break;
case WM_CONTEXTMENU:
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
ptInClient = point;
ScreenToClient(hWnd, &ptInClient);
GetClientRect(hWnd, &rect);
if (ptInClient.x < rect.right / 2)
TrackPopupMenuEx(hMenuShape, 0, point.x, point.y, hWnd, NULL);
else
TrackPopupMenuEx(hMenuColor, 0, point.x, point.y, hWnd, NULL);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
/* : IDM_OPEN, IDM_CLOSE,
IDM_SAVE, IDM_EXIT, IDM_SHOW_SHAPE, IDM_HIDE_SHAPE - 6.1
*/
case ID_RECTANGLE:
shapeData.id_shape = ID_RECTANGLE;
CheckMenuRadioItem(hMenuShape, ID_RECTANGLE,
ID_ELLIPSE, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_RHOMB:
shapeData.id_shape = ID_RHOMB;
CheckMenuRadioItem(hMenuShape, ID_RECTANGLE,
ID_ELLIPSE, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_ELLIPSE:
shapeData.id_shape = ID_ELLIPSE;
CheckMenuRadioItem(hMenuShape, ID_RECTANGLE,
ID_ELLIPSE, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_RED:
shapeData.fRed = ~shapeData.fRed;
CheckMenuItem(hMenuColor, ID_RED,
MF_BYCOMMAND | shapeData.fRed? MF_CHECKED : MF_UNCHECKED);
break;
case ID_GREEN:
shapeData.fGreen = ~shapeData.fGreen;
CheckMenuItem(hMenuColor, ID_GREEN,
MF_BYCOMMAND | shapeData.fGreen? MF_CHECKED : MF_UNCHECKED);
break;
case ID_BLUE:
shapeData.fBlue = ~shapeData.fBlue;
CheckMenuItem(hMenuColor, ID_BLUE,
MF_BYCOMMAND | shapeData.fBlue? MF_CHECKED : MF_UNCHECKED);
break;
case ID_DARK:
shapeData.id_bright = ID_DARK;
298
6.
6.2 ()
CheckMenuRadioItem(hMenuColor, ID_DARK,
ID_LIGHT, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_MEDIUM:
shapeData.id_bright = ID_MEDIUM;
CheckMenuRadioItem(hMenuColor, ID_DARK,
ID_LIGHT, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_LIGHT:
shapeData.id_bright = ID_LIGHT;
CheckMenuRadioItem(hMenuColor, ID_DARK,
ID_LIGHT, LOWORD(wParam), MF_BYCOMMAND);
break;
/*
case IDM_ABOUT:
MessageBox(hWnd,
"MenuDemo2\nVersion 1.0\nCopyright: Finesoft Corporation, 2005.",
"About MenuDemo2", MB_OK);
break;
default:
break;
}
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
/* WM_PAINT - 6.1 */
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
. 6.8. MenuDemo2
299
WM_CONTEXTMENU ,
.
, point,
, ptInClient.
rect GetClientRect.
, TrackPopupMenuEx
hMenuShape.
, TrackPopupMenuEx hMenuColor.
. 6.8 hMenuColor.
(keyboard accelerator) ,
WM_COMMAND WM_SYSCOMMAND.
,
. . 6.2
File Visual Studio.
, New , FileNew,
Ctrl+N. , .
, , .
. , Windows
, .
Windows WM_COMMAND
, TranslateAccelerator.
, ,
, . ,
.
,
:
1. ,
.
2. .
3. .
4. WinMain.
, ,
, . ,
, , .
Menu Item
Properties (. . 6.5) , Caption,
\t< >.
300
6.
, Ctrl+O
&Open... File,
\tCtrl+O. Caption &Open...\tCtrl+O.
.
InsertResource
Visual Studio. Insert Resource
Accelerator, New.
(. 6.9).
. 6.9.
ID .
,
. ,
&Open... File MenuDemo1,
IDM_OPEN.
Type VirtKey,
Key .
. 4.3 ( 4).
Key .
.
Modifiers ,
, .
, Ctrl+O &Open...,
Ctrl, Key O (
O ).
301
. .
LoadAccelerators:
HACCEL LoadAccelerators (
HINSTANCE hInstance, //
LPCTSTR lpTableName
//
);
IDR_ACCELERATOR1,
, MAKEINTRESOURCE.
. NULL.
, ,
,
. TranslateAccelerator:
int TranslateAccelerator
HWND hWnd,
//
HACCEL hAccTable, //
LPMSG lpMsg
//
);
(
MSG
WM_KEYDOWN WM_SYSKEYDOWN1
WM_COMMAND WM_SYSCOMMAND,
( Ctrl, Alt Shift).
,
wParam,
, . TranslateAccelerator
, .
TranslateAccelerator ,
,
.
1
4.
302
6.
TranslateMessage
DispatchMessage.
,
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
:
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
hMainWnd .
MenuDemo3
MenuDemo3 MenuDemo1.
,
,
.
. 6.11.
6.11. MenuDemo3
File
Shape
Color
Ctrl+O
&Open
IDM_OPEN
Sa&ve
IDM_SAVE
Ctrl+S
&Rectangle
ID_RECTANGLE
F2
Rhom&b
ID_RHOMB
F3
&Ellipse
ID_ELLIPSE
F4
&Red
ID_RED
Ctrl+R
&Green
ID_GREEN
Ctrl+G
&Blue
ID_BLUE
Ctrl+B
&Dark
ID_DARK
F10
&Medium
ID_MEDIUM
F11
&Light
ID_LIGHT
F12
MenuDemo3.
MenuDemo1 MenuDemo3 .cpp, .h .rc,
MenuDemo1 MenuDemo3.
. Workspace ResourceView
, IDR_MENU1.
, . 6.11,
\t< >,
. 6.11.
. ,
. 6.11.
303
F2, F3 Key
VK_F2, VK_F31 . . Ctrl.
MenuDemo3.cpp 6.3.
6.3. MenuDemo3
//////////////////////////////////////////////////////////////////////
// MenuDemo3.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "resource.h"
#define W 200
//
#define H 140
//
enum ShapeSize { MAX, MIN };
typedef struct {
int id_shape;
BOOL fRed;
BOOL fGreen;
BOOL fBlue;
int id_bright;
} ShapeData;
//
//
//
//
//
}
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* 6.1
*/
}
//////////////////////////////////////////////////////////////////////
MenuDemo3.exe,
.
1
. 4.3 ( 4).
304
7.
, (dialog box),
Windows.
, .
(controls), .
, ,
(, , ) ,
.
,
Windows .
, Windows, ,
,
. ,
Tab.
(dialog box manager).
,
, ,
(dialog procedure).
, ,
.
,
, ,
.
: ) , ,
) .
, .
(modal) (modeless).
.
305
,
,
.
.
, OK Cancel.
, .
(system modal) ,
. ,
, Windows.
.
. ,
. ,
,
.
. Windows
, . 7.1.
7.1.
(Picture control)
, ,
STATIC
(Static text)
.
( )
.
STATIC
(Group box)
BUTTON
(Button)
, ,
-
BUTTON
(Check box)
, ,
,
BUTTON
(Radio button)
,
.
BUTTON
(List box)
(),
LISTBOX
306
7.
7.1. ()
(Edit box)
(Combo box)
.
,
EDIT
(Scroll bar)
SCROLLBAR
COMBOBOX
Windows 95,
(common control library). ,
,
.
.
.
.
.
, ,
Windows .
. ,
HWND.
(MSDN)
.
,
. ,
, .
GetDlgItem:
HWND GetDlgItem (
HWND hDlg,
int nIDDlgItem
);
//
//
, NULL.
,
.
GetDlgCtrlID:
int GetDlgCtrlID (
HWND hwndCtl
//
);
,
. , ,
CreateWindiow,
(. . 1.7 1).
.
307
(enabled)
(disabled).
.
.
EnableWindow.
:
1. .
2. .
3. .
4. .
.
:
_ DIALOG DISCARDABLE x, y, width, height
[ _ ]
BEGIN
END
_ Windows C
, .
,
(. 5).
x, y, width, height .
x, y ,
. ,
.
,
STYLE, CAPTION, FONT .
STYLE dwStyle CreateWindow.
WS_POPUP WS_DLGFRAME.
CAPTION ,
WS_CAPTION.
. ,
.
.
,
.
308
7.
. , x, y,
width, height,
, (dialog template units).
.
.
.
.
,
X Y .
GetDialogBaseUnits. 32
, (baseunitX),
(baseunitY). ,
templateunitX, templateunitY
:
pixelX = templateunitX * baseunitX / 4;
pixelY = templateunitY * baseunitY / 8;
,
.
Windows (96 ).
GetDialogBaseUnits baseunitX = 8, baseunitY = 16.
.
: ,
.
.
(120 )
, ,
GetDialogBaseUnits baseunitX = 10, baseunitY = 20. Windows
,
.
.
FONT.
DlgDemo1.
309
DlgDemo1 MenuDemo1,
. ,
About MessageBox
, .
,
Windows.
.
.
DlgDemo1 About
,
. DlgDemo1
, MenuDemo1.
, DlgDemo1.
MenuDemo1 (. 6.1) DlgDemo1
.cpp, .h .rc, MenuDemo1
DlgDemo1. .
recource.h
// Used by MenuDemo1.rc
:
// Used by DlgDemo1.rc
Visual Studio InsertResource.
Insert Resource Dialog New.
(. 7.1). OK Cancel.
. 7.1.
Visual Studio
Controls (. 7.2).
, .
310
7.
. 7.2. Controls
Controls ,
Visual Studio
Controls.
.
Dialog Properties (. 7.3),
.
,
Properties.
311
OK .
, .
.
, , ,
Butterfly.bmp 64 90 ,
. 7.4.
. 7.4. Butterfly.bmp
,
DlgDemo1 , (www.piter.com).
,
.
.
,
. .
,
Butterfly.bmp IDB_BUTTERFLY.
,
. Picture,
Controls.
, (. 7.5).
. 7.5. Picture
, .
Picture
(. 7.6).
312
7.
ID IDC_STATIC_BFLY. Type
Bitmap.
Image. IDB_BUTTERFLY,
.
.
General , .
Visible.
, .
ShowWindow, ,
SW_HIDE.
Styles Sunken,
.
Styles . ,
Notify,
STN_CLICKED STN_DBLCLK,
.
Picture Properties.
Picture
, . 7.7. Static
.
. Static Text
.
Static, . 7.7.
313
Static ,
.
(. 7.8).
Static Text
IDC_STATIC.
(,
Caption), .
.
ID IDC_STATIC_1,
.
Caption ,
Static Text.
\t () \n ( ).
Caption DlgDemo1.
Styles (. 7.9).
Align text
. Left ( ), Center Right.
Center vertically .
.
No prefix &.
, & . &
, .
Border .
Center Align text Center
vertically Border. Text Properties.
, . 7.10.
.
Static Text
314
7.
DlgDemo1.
:
ID
Caption
Align text
IDC_STATIC
Version 1.0
Center
Center vertically
IDC_STATIC
Center
Center vertically
,
. 7.11.
. 7.10. IDC_STATIC_1
. 7.11.
.
. ,
, ,
. ,
.
Visual Studio
. ,
Visual Studio Layout,
. Layout
.
315
, Ctrl ,
, ,
. , , ,
.
Layout.
. ,
,
Make Same Size,
Width ( ), Height ( ), Both ( ).
Align.
Left (
) Right ( ).
Space Evenly
( Across)
( Down). Center in Dialog
, ( Horizontal),
( Vertical).
Arrange Buttons
,
.
Layout
DlgDemo1.
Make Same Size,
Static Text, Align
DlgDemo1 Space Evenly
. . 7.12
.
. 7.12.
, .
OK,
. . 7.13 ,
, , .
Tab stop.
WS_TABSTOP, , OK
. .
316
7.
. 7.13. OK
Styles, ,
Default button. ,
. ,
, .
DlgDemo1.
DlgDemo1.cpp, ,
MenuDemo1.cpp 6.1.
, 7.1.
7.1. DlgDemo1
//////////////////////////////////////////////////////////////////////
// DlgDemo1.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "resource.h"
#define W 200
//
#define H 140
//
enum ShapeSize { MAX, MIN };
typedef struct {
int id_shape;
BOOL fRed;
BOOL fGreen;
BOOL fBlue;
int id_bright;
} ShapeData;
//
//
//
//
//
317
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInst;
/* - 6.1 */
switch (uMsg)
{
case WM_CREATE:
hInst = GetModuleHandle(NULL);
/* WM_CREATE - 6.1
break;
*/
case WM_COMMAND:
switch (LOWORD(wParam))
{
/*
IDM_OPEN, IDM_CLOSE, ... , IDM_RESIZE
6.1
*/
case IDM_ABOUT:
//
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutDlgProc);
break;
default:
break;
}
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
/* WM_PAINT 6.1
break;
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
//
318
7.
7.1 ()
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
AboutDlgProc .
CALLBACK,
. ,
DlgProc.
AboutDlgProc ,
.
:
LRESULT,
BOOL.
,
DefWindowProc.
, FALSE.
, TRUE.
WM_CREATE.
WM_INITDIALOG.
WM_PAINT,
.
WM_INITDIALOG ,
.
TRUE, Windows
, WS_TABSTOP.
WS_TABSTOP OK.
WM_INITDIALOG
SetFocus ,
. FALSE.
WM_INITDIALOG
, .
319
, ,
WM_COMMAND. , WM_COMMAND
, wParam
, wParam ,
lParam .
WM_COMMAND. OK
IDOK. ,
Enter .
,
IDCANCEL.
,
Alt+F4.
,
EndDialog, TRUE.
FALSE.
EndDialog .
:
BOOL EndDialog (
HWND hDlg,
INT_PTR nResult
);
//
// , DialogBox
EndDialog ,
DialogBox ( )
DialogBox. EndDialog nResult
TRUE IDOK FALSE
IDCANCEL.
DlgDemo1 DialogBox ,
,
.
About . WM_COMMAND,
, .
About wParam WM_COMMAND
IDM_ABOUT.
MenuDemo1, ,
MessageBox.
DialogBox:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutDlgProc);
, WM_CREATE,
,
.
DialogBox ,
IDD_ABOUT. , DialogBox Windows,
AboutDlgProc.
320
7.
DialogBox CreateWindowEx
. WM_INITDIALOG
, , (
)
.
DialogBox WndProc ,
.
EndDialog, DialogBox
,
,
nResult, EndDialog.
. ,
MenuDemo1.
About. ,
, . 7.14.
. , ,
, MenuDemo1
MessageBox.
,
.
? ,
?..
Win32 API.
. ,
EnableWindow, :
BOOL EnableWindow(
HWND hWnd,
//
BOOL bEnable //
};
321
.
TRUE, .
FALSE, .
:
, ;
( Caption)
, ,
SetWindowText.
,
.
, hWndControl
hDlg ID, GetDlgItem:
hWndControl = GetDlgItem(hDlg, ID);
.
. 7.14.
(Static Text)
,
.
. ,
.
WM_SETFONT . ,
SendMessage.
SendMessage .
:
SendMessage (
(HWND) hWnd,
WM_SETFONT,
(WPARAM) wParam;
(LPARAM) lParam;
);
//
//
//
//
wParam NULL,
. TRUE lParam
.
Static Text Edit Box,
(readonly),
WM_CTLCOLORSTATIC , .
wParam
, lParam
. wParam
HDC, lParam HWND.
322
7.
WM_CTLCOLORSTATIC,
,
. ,
.
WM_CTLCOLORSTATIC,
HBRUSH,
.
. DlgDemo1,
. 7.1
AboutDlgProc :
//====================================================================
//
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
static HWND hStatic1;
static LOGFONT lf; // static !
HFONT hFont1;
switch (uMsg) {
case WM_INITDIALOG:
hStatic1 = GetDlgItem(hDlg, IDC_STATIC_1);
// Verdana
lf.lfHeight = 28;
lstrcpy( (LPSTR)&lf.lfFaceName, "Verdana" );
hFont1 = CreateFontIndirect(&lf);
// hStatic1
SendMessage(hStatic1, WM_SETFONT, (WPARAM)hFont1, TRUE );
return TRUE;
case WM_CTLCOLORSTATIC:
// hStatic1
if ((HWND)lParam == hStatic1) {
SetTextColor((HDC)wParam, RGB(160, 0, 0));
SetBkMode((HDC)wParam, TRANSPARENT);
return (DWORD)GetSysColorBrush(COLOR_3DFACE);
}
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
DeleteObject(hFont1);
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
323
IDC_STATIC_1
WM_INITDIALOG,
WM_CTLCOLORSTATIC.
WM_CTLCOLORSTATIC ,
hStatic1,
, COLOR_3DFACE.
Static Text,
.
, (HBRUSH)
.
DlgDemo1
About DlgDemo1, . 7.15.
. 7.15. DlgDemo1
DlgDemo1
Picture Static Text.
STATIC.
,
, (Button), (Check box),
(Radio button) (Group box).
BUTTON.
324
7.
,
, .
MSDN. ,
, Tab.
SetFocus ,
. DlgDemo2,
,
DrawFocusRect.
Button
, /
.
DlgDemo1 OK,
, .
,
.
,
, ,
Button Controls.
Push Button Properties General (. . 7.13)
ID , Caption ,
.
Button
IDC_BUTTON1, IDC_BUTTON2 . ,
.
.
Styles (. 7.16) .
Default button .
Owner draw ,
. ,
.
Icon Bitmap ,
.
325
Multiline , ,
.
Flat .
Styles ,
, . 7.16.
, (Owner
draw), .
Owner draw
Owner draw,
BS_OWNERDRAW.
BS_OWNERDRAW ,
WM_DRAWITEM.
,
, ,
.
WM_DRAWITEM, wParam
, lParam
DRAWITEMSTRUCT. WM_DRAWITEM
Owner draw,
Combo box, List box List view, .
DRAWITEMSTRUCT :
typedef struct {
UINT
CtlType;
UINT
CtlID;
UINT
itemID;
UINT
itemAction;
UINT
itemState;
HWND
hwndItem;
HDC
hDC;
RECT
rcItem;
ULONG_PTR itemData;
} DRAWITEMSTRUCT;
CtlType .
. 7.2.
7.2. CtlType
CtlType
ODT_BUTTON
ODT_COMBOBOX
ODT_LISTBOX
ODT_LISTVIEW
ODT_MENU
ODT_STATIC
Owner draw
Combo box Owner draw
List box Owner draw
List control Owner draw
Owner draw
Static control Owner draw
ODT_TAB
326
7.
CtlID .
, .
itemID
Combo box List box.
itemAction , .
, . 7.3.
7.3. itemAction
itemAction
ODA_DRAWENTIRE
ODA_FOCUS
.
, ODS_FOCUS
itemState
ODA_SELECT
() . ,
ODS_SELECTED itemState
itemState
. ODS_FOCUS ODS_SELECTED
. 7.3.
MSDN.
hDC
.
.
rcItem ,
.
hDC.
WM_DRAWITEM,
hDC, .
.
Owner draw
Owner draw
DlgDemo1. , DlgDemo2,
About
OK.
DlgDemo2.
DlgDemo1 (. 7.1) DlgDemo2 .cpp,
.h .rc, DlgDemo1 DlgDemo2.
. DlgDemo2.cpp DlgDemo1
DlgDemo2.
Butterfly.bmp,
BtnActive.bmp.
, , .
.
BtnNoActive.bmp
, BtnPress.bmp
327
1. ,
. , ,
, .
IDD_ABOUT.
Resource View Workspace
IDD_ABOUT.
, . 7.12.
IDD_ABOUT About
DlgDemo1 About DlgDemo2. IDC_STATIC_1
DlgDemo1 DlgDemo2.
OK . ,
. 7.12, , ,
. DlgDemo2,
.
Button
, . 7.17.
IDOK, Caption .
Styles Owner draw.
IDOK .
ID_ABOUT_HELP, Caption
Help. ,
. 7.17.
. 7.17.
.
Resource View Workspace. Bitmap
IDB_BUTTERFLY.
Import, :
IDB_PICT_0
BtnNoActive.bmp
IDB_PICT_1
BtnActive.bmp
IDB_PICT_2
BtnPress.bmp
,
http://www.piter.com.
328
7.
.
DlgDemo2.cpp,
AboutDlgProc. 7.2 .
7.2. AboutDlgProc DlgDemo2.cpp
//====================================================================
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
HINSTANCE hInst;
static HWND hStatic1;
static LOGFONT lf; // static !
static HFONT hFont1, hFont2;
static
static
static
static
static
static
static
static
static
HBITMAP hPict0;
HBITMAP hPict1;
HBITMAP hPict2;
HBRUSH hBrush0;
HBRUSH hBrush1;
HBRUSH hBrush2;
HBRUSH hCurBrush;
HDC hMemDC;
BITMAP bm;
//
//
//
//
//
//
//
//
//
LPDRAWITEMSTRUCT pdis;
static HWND hBtnOk, hBtnHelp;
static RECT rcBtnHelp, rect;
int x0, y0 = 0;
switch (uMsg) {
case WM_INITDIALOG:
hInst = GetModuleHandle(NULL);
hStatic1 = GetDlgItem(hDlg, IDC_STATIC_1);
hBtnOk = GetDlgItem(hDlg, IDOK);
hBtnHelp = GetDlgItem(hDlg, ID_ABOUT_HELP);
GetWindowRect(hBtnHelp, &rcBtnHelp);
// Verdana
lf.lfHeight = 28;
lstrcpy( (LPSTR)&lf.lfFaceName, "Verdana" );
hFont1 = CreateFontIndirect(&lf);
lf.lfHeight = 20;
hFont2 = CreateFontIndirect(&lf);
// hStatic1
SendMessage(hStatic1, WM_SETFONT, (WPARAM)hFont1, TRUE );
// IDOK
hPict0 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_PICT_0));
hPict1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_PICT_1));
hPict2 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_PICT_2));
hBrush0 = CreateSolidBrush(RGB(214, 214, 214));
hBrush1 = CreateSolidBrush(RGB(149, 242, 242));
hBrush2 = CreateSolidBrush(RGB(83, 52, 254));
GetObject(hPict0, sizeof(bm), (LPSTR)&bm);
SetFocus(hBtnHelp);
329
// ,
// Owner draw
pdis = (LPDRAWITEMSTRUCT)lParam;
hMemDC = CreateCompatibleDC(pdis->hDC);
// ,
switch (pdis->itemAction) {
case ODA_FOCUS:
if (pdis->itemState & ODS_FOCUS) {
SelectObject(hMemDC, hPict1);
hCurBrush = hBrush1;
}
else {
SelectObject(hMemDC, hPict0);
hCurBrush = hBrush0;
}
break;
case ODA_SELECT:
if (pdis->itemState & ODS_SELECTED) {
SelectObject(hMemDC, hPict2);
hCurBrush = hBrush2;
}
break;
default:
SelectObject(hMemDC, hPict0);
hCurBrush = hBrush0;
} // end of switch
//
FillRect(pdis->hDC, &pdis->rcItem, hCurBrush);
x0 = ((pdis->rcItem.right - pdis->rcItem.left) - bm.bmWidth) / 2;
// ...
BitBlt(pdis->hDC, x0, y0, bm.bmWidth, bm.bmHeight,
hMemDC, 0, 0, SRCCOPY);
//
SelectObject(pdis->hDC, hFont2);
SetBkMode(pdis->hDC, TRANSPARENT);
SetTextColor(pdis->hDC, RGB(255, 255, 255));
TextOut(pdis->hDC, 32, 74, "OK", 2);
SetTextColor(pdis->hDC, RGB(100, 100, 100));
TextOut(pdis->hDC, 30, 72, "OK", 2);
//
FrameRect(pdis->hDC, &pdis->rcItem,
(HBRUSH)GetStockObject(BLACK_BRUSH));
DeleteDC(hMemDC); // !!! hMemDC
330
7.
7.2 ()
return TRUE;
case WM_SETCURSOR: //
if ((HWND)wParam == hBtnOk)
if (GetFocus() != hBtnOk) SetFocus(hBtnOk);
if ((HWND)wParam == hBtnHelp) {
if (GetFocus() != hBtnHelp) {
SetFocus(hBtnHelp);
// DrawFocusRect
SetRect(&rect, 3, 3, rcBtnHelp.right - rcBtnHelp.left - 3,
rcBtnHelp.bottom - rcBtnHelp.top - 3);
DrawFocusRect(GetDC(hBtnHelp), &rect);
}
}
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case ID_ABOUT_HELP:
MessageBox(hDlg, "
'Owner draw'", "HELP", MB_OK);
return TRUE;
case IDOK:
case IDCANCEL:
DeleteObject(hFont1);
DeleteObject(hFont2);
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
WM_DRAWITEM WM_SETCURSOR.
WM_DRAWITEM IDOK
, .
hMemDC
, hPict0, hPict1 hPict2.
BitBlt.
FillRect hCurBrush.
.
, ,
, . OK
, .
. ,
IDOK ,
.
, .
Tab
WS_TABSTOP , .
331
,
,
. , Windows
,
WM_SETCURSOR.
WM_SETCURSOR
.
IDD_ABOUT.
AboutDlgProc WM_SETCURSOR, wParam
, .
hBtnOk hBtnHelp ,
SetFocus, .
, BS_OWNERDRAW,
DrawFocusRect,
.
. 7.18 About DlgDemo2
OK.
OK ,
, DlgDemo2
.
(Check box)
, .
.
(),
.
.
Visual
Studio. ,
.
,
Check Box Properties. . 7.19 Styles
.
332
7.
. 7.19. Styles
Auto . .
,
.
. Auto,
WM_COMMAND, ,
CheckDlgButton .
Left text ,
.
Tri-state ,
.
, .
,
.
Push-like ,
.
.
Flat ,
.
Icon Bitmap ,
. ,
.
Auto
,
. CheckDlgButton:
BOOL CheckDlgButton
HWND hDlg,
int nIDButton,
UINT uCheck
);
(
//
//
//
uCheck , . 7.4.
7.4. uCheck
BST_UNCHECKED
BST_CHECKED
BST_INDETERMINATE
0x0000
0x0001
0x0002
(state to grayed).
,
Tri-state
333
(Radio button) , ,
. , .
, ,
. ,
, .
Radio Button Properties,
, Auto,
. Auto
, WM_COMMAND,
, CheckRadioButton
.
,
Group
General. ( )
Group .
Group, ,
Radio button.
. ,
. ,
Visual Studio (
).
Auto
,
CheckRadioButton:
BOOL CheckRadioButton (
HWND hDlg,
//
int nIDFirstButton, //
int nIDLastButton, //
int nIDCheckButton //
);
(Group box) ,
.
BUTTON (.
. 7.1). ,
. WM_COMMAND.
,
.
334
7.
.
. ,
, , .
,
.
.
, Group Tab stop (
General ),
.
,
,
DlgDemo3,
DlgDemo1.
. ,
DlgDemo1 DrawShape.
Shape ,
Color Red, Green, Blue Color
, Dark, Medium, Light. , ,
, DrawShape ,
.
. DlgDemo3.
DlgDemo1 DlgDemo3 .cpp, .h
.rc, DlgDemo1 DlgDemo3.
. Butterfly.bmp.
DlgDemo3
Workspace ResourceView,
Menu IDR_MENU1 .
Menu Item Properties Draw shape.
Pop-up.
, Draw
shape (. 7.20).
. 7.20. Pop-up
, OK. ,
ID .
IDM_DRAW_SHAPE. Draw Shape.
335
. .
InsertResource, Dialog
New. ,
. ID IDD_SHAPE_PARAM.
Styles Title bar,
.
.
, OK Cancel. Layout
Arrange ButtonsBottom, .
.
, ,
, . 7.21.
. 7.21. IDD_SHAPE_PARAM
. 7.5. Tab stop Group
.
7.5. IDD_SHAPE_PARAM
ID
Caption
Tab stop
Group
Group box
IDC_STATIC
Shape
Radio button
ID_RECTANGLE
Rectangle
Radio button
ID_RHOMB
Rhomb
Radio button
ID_ELLIPSE
Ellipse
Group box
IDC_STATIC
Color components
Check box
ID_RED
Red
Check box
ID_GREEN
Green
Check box
ID_BLUE
Blue
Group box
IDC_STATIC
Color intensity
336
7.
7.5 ()
ID
Caption
Tab stop
Group
Radio button
Radio button
ID_DARK
ID_MEDIUM
Dark
Medium
Radio button
ID_LIGHT
Light
Save Visual Studio.
IDD_ABOUT
Workspace ResourceView
IDD_ABOUT. Dialog Properties Caption
About DlgDemo3. Text Properties
IDC_STATIC_1 DlgDemo1 DlgDemo3.
DlgDemo3.cpp , 7.3.
7.3. DlgDemo3
//////////////////////////////////////////////////////////////////////
// DlgDemo3.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "resource.h"
#define W
#define H
200
140
//
//
//
//
//
//
//
ShapeData shapeData;
//
// ShapeParamDlgProc WndProc
337
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInst;
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
static HMENU hMenu; //
int x0, y0, x1, y1, x2, y2;
POINT pt[4];
static ShapeSize shapeSize = MIN;
static BOOL bShow = TRUE;
static HBRUSH hBrush, hOldBrush;
char* itemResizeName[2] = { "Decrease!", "Increase!"};
int intensity[3] = { 85, 170, 255 }; // RGB-
int brightness;
switch (uMsg)
{
case WM_CREATE:
hInst = GetModuleHandle(NULL);
hMenu = GetMenu(hWnd);
SetMenuDefaultItem(GetSubMenu(hMenu, 0), IDM_OPEN, FALSE);
CheckMenuRadioItem(GetSubMenu(hMenu, 1), IDM_SHOW_SHAPE,
IDM_HIDE_SHAPE, IDM_SHOW_SHAPE, MF_BYCOMMAND);
shapeData.id_shape = ID_RECTANGLE;
shapeData.id_bright = ID_DARK;
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
/*
IDM_OPEN, IDM_CLOSE, ... , IDM_RESIZE
6.1
*/
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutDlgProc);
break;
case IDM_DRAW_SHAPE:
DialogBox(hInst, MAKEINTRESOURCE(IDD_SHAPE_PARAM),
hWnd, ShapeParamDlgProc);
break;
default:
break;
}
338
7.
7.3 ()
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
/* WM_PAINT 6.1
*/
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
/* - 7.1 ( ) */
}
//====================================================================
BOOL CALLBACK ShapeParamDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
static ShapeData shapeDataNew;
switch (uMsg) {
case WM_INITDIALOG:
CheckRadioButton(hDlg, ID_RECTANGLE, ID_ELLIPSE, shapeData.id_shape);
CheckRadioButton(hDlg, ID_DARK, ID_LIGHT, shapeData.id_bright);
CheckDlgButton(hDlg, ID_RED, shapeData.fRed);
CheckDlgButton(hDlg, ID_GREEN, shapeData.fGreen);
CheckDlgButton(hDlg, ID_BLUE, shapeData.fBlue);
shapeDataNew = shapeData;
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case ID_RECTANGLE:
case ID_RHOMB:
case ID_ELLIPSE:
shapeDataNew.id_shape = LOWORD(wParam);
return TRUE;
case ID_RED:
shapeDataNew.fRed = ~shapeDataNew.fRed;
return TRUE;
case ID_GREEN:
shapeDataNew.fGreen = ~shapeDataNew.fGreen;
339
return TRUE;
case ID_BLUE:
shapeDataNew.fBlue = ~shapeDataNew.fBlue;
return TRUE;
case ID_DARK:
case ID_MEDIUM:
case ID_LIGHT:
shapeDataNew.id_bright = LOWORD(wParam);
return TRUE;
case IDOK:
shapeData = shapeDataNew;
EndDialog(hDlg, TRUE);
return TRUE;
case IDCANCEL:
EndDialog(hDlg, FALSE);
return TRUE;
}
break;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
, ,
. , shapeData ,
WndProc.
WndProc ShapeParamDlgProc.
shapeData .
.
ShapeParamDlgProc,
IDD_SHAPE_PARAM. WM_INITDIALOG,
.
, Auto,
,
.
, shapeData.
CheckRadioButton CheckDlgButton.
, ShapeParamDlgProc
shapeData shapeDataNew.
shapeDataNew
WM_COMMAND.
OK IDOK,
shapeData shapeDataNew.
Cancel IDCANCEL,
shapeData , .
WndProc WM_COMMAND
:
case IDM_DRAW_SHAPE:
DialogBox(hInst, MAKEINTRESOURCE(IDD_SHAPE_PARAM),
hWnd, ShapeParamDlgProc);
break;
340
7.
DialogBox
IDD_SHAPE_PARAM.
, DlgDemo3.
Windows
.
Tab
. Tab
, WS_TABSTOP (
Tab stop), .
.
. .
Tab,
. ,
, .
,
.
Tab stop, ,
Group. , Tab stop Group,
.
. 7.22. IDD_SHAPE_PARAM
341
. Visual
Studio .
, Layout,
Tab order. ,
, ,
.
. ,
IDD_SHAPE_PARAM DlgDemo3
. 7.22.
Edit box List box.
(Edit box),
, ,
. Edit box
EDIT.
:
, Microsoft Notepad.
,
, , , ,
, Shift ,
Windows,
.
Edit box ,
. Edit Properties
General ID .
Styles, . 7.23,
.
. 7.23. Styles
,
( Auto HScroll), (
Border) (Left).
Align text,
(Centered Right).
342
7.
Multiline,
.
Horizontal scroll, Vertical scroll, Auto VScroll.
Number
.
, Password,
.
No hide selection
, . OEM
convert ,
Windows OEM, .
CharToOem.
Want return .
, Enter
. , Enter
,
.
Ctrl+Enter.
Uppercase Lowercase
.
, .
Read-only ,
.
Edit box
32 .
hwndEdit :
SendMessage(hwndEdit, _, wParam, lParam);
hwndEdit .
Win32 API SendDlgItemMessage
, :
SendDlgItemMessage(hDlg, nIDD, _, wParam, lParam);
hDlg , nIDD
. ,
SendMessage,
. .
. 7.6
.
7.6.
wParam
lParam
EM_SETSEL
iStart
iEnd
EM_GETSEL
&iStart
&iEnd
, iStart
iEnd
WM_CLEAR
343
wParam
lParam
WM_CUT
Windows
WM_COPY
Windows
WM_PASTE
WM_GETTEXT
nMax
szBuffer
( nMax )
szBuffer
EM_GETLINECOUNT
EM_LINELENGTH
iLine
iLine
EM_GETLINE
iLine
szBuffer
iLine
szBuffer
Edit box
WM_COMMAND.
wParam , wParam
, lParam .
. 7.7.
7.7. Edit box
EN_SETFOCUS
EN_KILLFOCUS
EN_UPDATE
EN_CHANGE
EN_ERRSPACE
,
WM_CTLCOLOREDIT,
WM_CTLCOLORSTATIC.
,
,
DlgDemo1 Static Text.
/
Win32 API GetDlgItemText, SetDlgItemText GetDlgItemInt,
,
.
,
, , , .
GetDlgItemText :
UINT GetDlgItemText(HWND hDlg, int ctrlID, LPTSTR lpString, int nMaxCount);
, ,
ctrlID,
344
7.
lpString. nMaxCount ,
lpString.
, , .
.
SetDlgItemText, ,
, lpString,
ctrlID.
GetDlgItemInt
UINT GetDlgItemInt(HWND hDlg, int ctrlID, BOOL* lpTranslated, BOOL bSigned);
ctrlID .
, .
,
, .
lpTranslated BOOL,
,
. TRUE .
, NULL.
bSigned TRUE,
int,
UINT.
.
GetDlgItemInt ,
INT_MAX (2147483647) UINT_MAX
(4294967295) .
GetDlgItemText SetDlgItemText
7.4.
(List box) ,
, .
,
.
, List box .
Open,
FileOpen Visual Studio.
,
, ,
. Windows
, .
. ,
.
, .
,
.
345
,
. ,
.
List box ,
. List Box Properties
General ID .
Styles, . 7.24, .
. 7.24. Styles
(Single),
(Border), (Sort)
(Vertical scroll).
No integral height , List box
, .
, Windows ,
.
Selection . Single
:
Multiple
. ,
Extended
.
Shift
None
, ,
Fixed
Owner draw.
WM_MEASUREITEM WM_DRAWITEM,
Variable
, Fixed, ,
.
WM_DRAWITEM WM_MEASUREITEM
346
7.
LB_GETTEXT.
Multi-column ,
.
Horizontal scroll.
LB_SETCOLUMNWIDTH.
No redraw ,
WM_PAINT .
WM_SETREDRAW.
Disable no scroll
, .
,
. ,
, .
hwndList,
SendMessage(hwndList, _, wParam, lParam);
SendDlgItemMessage(hDlg, IDC_LIST, _, wParam, lParam);
IDC_LIST .
. 7.8.
7.8.
wParam
lParam
LB_ADDSTRING
szString
LB_DELETESTRING
LB_FINDSTRING
iIndex
iStart
0
szString
LB_GETCOUNT
LB_GETCURSEL
0
0
0
0
LB_GETSELCOUNT
LB_GETSELITEMS
nMax
pBuf
szString.
Sort ,
.
,
iIndex
,
szString. iStart + 1. wParam 1,
. LB_ERR,
LB_ERR,
.
( )
pBuf
. nMax
347
wParam
lParam
LB_GETTEXT
iIndex
szString
iIndex
szString. .
, LB_GETTEXTLEN.
LB_GETTEXTLEN
iIndex
iIndex
LB_INSERTSTRING
iIndex
szString
LB_RESETCONTENT
LB_SELECTSTRING
iStart
szString
,
LB_FINDSTRING,
LB_SETCURSEL
iIndex
iIndex (
)
LB_SETSEL
wParam
iIndex
iIndex (
). wParam
TRUE, ,
FALSE . lParam
1,
iIndex,
, .
SendMessage ,
,
. LB_OK (0) ,
LB_ERRSPACE (2)
, LB_ERR (1) .
,
WM_COMMAND,
wParam .
. 7.9.
7.9. List box
LBN_SETFOCUS
LBN_KILLFOCUS
LBN_SELCHANGE
( Notify)
LBN_DBLCLK
(
Notify)
LBN_ERRSPACE
348
7.
.
:
( ..), 20 ;
( 20 );
( 20 );
( 80 ).
, notebook.dat. ,
, , . 7.10.
0 1 20
21 22 41
42 43 62
63 64 143
, ,
.
C.
, ,
List box. ,
.
,
( ).
, ,
(Edit box)
.
Win32 Application MyNotebook1.
IDR_MENU1 .
IDM_VIEW.
. 7.25. IDD_VIEW
IDD_VIEW.
Title bar System menu.
349
. 7.25.
, , .
.
, .
, MyNotebook2, ,
.
:
ID
Group box
IDC_GROUP_0
Static text
IDC_STATIC
Caption
Static text
IDC_STATIC_PHONE
List box
IDC_LIST1
Button
IDC_REC_ADD
Button
IDC_REC_DELETE
Group box
IDC_GROUP_1
Static text
IDC_STATIC_ADDR
Edit box
IDC_INFO_ADDR
Multiline, Horizontal
scroll, Read-only
Static text
IDC_STATIC_BDAY
Edit box
IDC_INFO_BDAY
Read-only
IDD_ADD_REC
. .
IDD_ADD_REC .
. 7.26.
. 7.26. IDD_ADD_REC
ID
Caption
Static text
IDC_STATIC
Static text
IDC_STATIC
Static text
IDC_STATIC
350
7.
ID
Caption
Static text
Edit box
Edit box
Edit box
Edit box
IDC_STATIC_BDAY
IDC_INPUT_NAME
IDC_INPUT_PHONE
IDC_INPUT_ADDR
IDC_INPUT_BDAY
. MyNotebook1.cpp,
7.4.
7.4. MyNotebook1
//////////////////////////////////////////////////////////////////////
// MyNotebook1.cpp
#include <windows.h>
#include <fstream>
using namespace std;
#include "KWnd.h"
#include "resource.h"
#define N1 21
#define N2 81
#define TOTAL_SIZE (3*N1 + N2)
fstream fdat;
struct SubStr {
char name[N1];
char phone[N1];
char birthday[N1];
char address[N2];
};
union Data {
SubStr ss;
char line[TOTAL_SIZE];
};
class ListItem {
char buf[TOTAL_SIZE];
public:
ListItem() { Clear(); }
// ( line )
void Clear() { memset(dat.line, ' ', TOTAL_SIZE); }
// line , ,
// ''
void DoOneString() {
int count = 0;
for (int i = TOTAL_SIZE - 1; i > 0; --i)
if (!dat.line[i])
if (!count) count++;
else dat.line[i] = ' ';
}
const char* GetBirthday() {
memcpy(buf, dat.ss.birthday, N1);
351
buf[N1-1] = 0;
return buf;
}
const char* GetAddress() {
memcpy(buf, dat.ss.address, N2);
buf[N2-1] = 0;
return buf;
}
Data dat;
};
ListItem item;
BOOL CALLBACK ViewDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK AddRecDiaProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("MyNotebook1", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HINSTANCE hInst;
switch (uMsg) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_VIEW:
hInst = GetModuleHandle(NULL);
DialogBox(hInst, MAKEINTRESOURCE(IDD_VIEW), hWnd, ViewDlgProc);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
352
7.
7.4 ()
BOOL CALLBACK ViewDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
static HWND hListBox;
static HWND hEditInfoAddr, hEditInfoBday;
HWND hCtrl;
static LOGFONT lf;
HFONT hFont1;
COLORREF editInfoColor;
static HBRUSH hBrush;
int nItems;
//
int iCurItem; //
BOOL dlgYes;
int i;
switch (uMsg) {
case WM_INITDIALOG:
hListBox = GetDlgItem(hDlg, IDC_LIST1);
hEditInfoAddr = GetDlgItem(hDlg, IDC_INFO_ADDR);
hEditInfoBday = GetDlgItem(hDlg, IDC_INFO_BDAY);
// hListBox
lf.lfHeight = 16;
lstrcpy( (LPSTR)&lf.lfFaceName, "Courier" );
hFont1 = CreateFontIndirect(&lf);
SendMessage(hListBox, WM_SETFONT, (WPARAM)hFont1, TRUE );
//
editInfoColor = RGB(190, 255, 255);
hBrush = CreateSolidBrush(editInfoColor);
// " "
fdat.open("notebook.dat", ios::in);
if (!fdat) { fdat.clear(); return TRUE; }
else while (1) {
fdat.getline(item.dat.line, sizeof(Data));
if (fdat.eof()) { fdat.clear();
break; }
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)item.dat.line);
}
fdat.close();
return TRUE;
case WM_CTLCOLORSTATIC:
//
hCtrl = (HWND)lParam;
if ((hCtrl == hEditInfoAddr) || (hCtrl == hEditInfoBday)) {
SetBkColor((HDC)wParam, editInfoColor);
SetBkMode((HDC)wParam, TRANSPARENT);
return (DWORD)hBrush;
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
353
case IDC_REC_ADD:
dlgYes = DialogBox((HINSTANCE)GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_ADD_REC), hDlg, AddRecDiaProc);
if (dlgYes)
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)item.dat.line);
break;
case IDC_REC_DELETE:
iCurItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
if (iCurItem != LB_ERR) {
SendMessage(hListBox, LB_DELETESTRING, iCurItem, 0);
SetDlgItemText(hDlg, IDC_INFO_ADDR, "");
SetDlgItemText(hDlg, IDC_INFO_BDAY, "");
}
else {
MessageBox(hDlg, " ",
"", MB_OK);
break;
}
break;
case IDC_LIST1:
switch (HIWORD(wParam)) {
case LBN_SELCHANGE:
//
iCurItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
SendMessage(hListBox, LB_GETTEXT, iCurItem,
(LPARAM)item.dat.line);
SetDlgItemText(hDlg, IDC_INFO_ADDR, item.GetAddress());
SetDlgItemText(hDlg, IDC_INFO_BDAY, item.GetBirthday());
return TRUE;
}
break;
case IDOK:
fdat.open("notebook.dat", ios::out | ios::trunc);
if (!fdat) {
MessageBox(hDlg,
" 'notebook.dat' !",
"", MB_OK);
return FALSE;
}
nItems = SendMessage(hListBox, LB_GETCOUNT, 0, 0);
for (i = 0; i < nItems; ++i) {
SendMessage(hListBox, LB_GETTEXT, i, (LPARAM)item.dat.line);
fdat << item.dat.line << endl;
}
fdat.close();
EndDialog(hDlg, TRUE);
return TRUE;
case IDCANCEL:
EndDialog(hDlg, FALSE);
354
7.
7.4 ()
return TRUE;
}
break;
}
return FALSE;
}
//====================================================================
BOOL CALLBACK AddRecDiaProc(HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg, IDC_INPUT_NAME));
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
item.Clear();
GetDlgItemText(hDlg, IDC_INPUT_NAME, item.dat.ss.name, N1);
GetDlgItemText(hDlg, IDC_INPUT_PHONE, item.dat.ss.phone, N1);
GetDlgItemText(hDlg, IDC_INPUT_BDAY, item.dat.ss.birthday, N1);
GetDlgItemText(hDlg, IDC_INPUT_ADDR, item.dat.ss.address, N2);
item.DoOneString();
EndDialog(hDlg, TRUE);
return TRUE;
case IDCANCEL:
EndDialog(hDlg, FALSE);
return TRUE;
}
break;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
,
,
144 . C
. ,
,
C GetDlgItemText.
C. ,
,
: C C.
, ListItem.
dat, (union) Data.
line, ss, , name,
phone, birthday address.
355
DoOneString,
. dat.line
, ,
, . GetBirthday,
C dat.ss.birthday, GetAddress,
dat.ss.address.
item, ListItem,
.
ViewDlgProc,
AddRecDiaProc ViewDlgProc.
ViewDlgProc, IDD_VIEW,
.
WM_INITDIALOG
:
hFont1
. Courier,
,
. hListBox
WM_SETFONT.
hListBox. notebook.dat
,
LB_ADDSTRING.
WM_COMMAND :
IDC_REC_ADD,
DialogBox IDD_ADD_REC.
, .
OK, DialogBox TRUE
SendMessage LB_ADDSTRING.
IDC_REC_DELETE, ,
. ,
LB_DELETESTRING,
IDC_INFO_ADDR IDC_INFO_BDAY SetDlgItemText (
).
IDC_LIST1
LBN_SELCHANGE,
iCurItem. LB_GETTEXT. ,
item,
SetDlgItemText IDC_INFO_ADDR
IDC_INFO_BDAY.
IDOK,
notebook.dat.
356
7.
AddRecDiaProc
. item.DoOneString,
C.
. 7.27 MyNotebook1.
. 7.27. MyNotebook1
(Combo box),
, .
.
, .
Combo box
Controls. Combo box
, . 7.28.
. 7.28.
Combo box. ,
.
,
Layout. .
, .
, .
!
,
Combo box !
357
,
(. 7.29).
. 7.29.
, MSDN,
.
, , ,
Combo box,
.
Combo box
, Combo box Properties.
General ID
. Styles (. 7.30)
.
Simple
Dropdown
Drop List
Data. ,
MFC, Data
, Combo box.
DLGINIT. , Win32 API,
,
358
7.
DLGINIT.
CB_ADDSTRING.
Edit box List box. ,
Combo box, CB_,
, Combo box ,
CBN_.
. 7.11 ,
Combo box, ,
Edit box List box.
7.11. Edit box, List box
Combo box
Edit box List box
Combo box
EM_GETSEL
CB_GETEDITSEL
EM_SETSEL
CB_SETEDITSEL
LB_ADDSTRING
CB_ADDSTRING
LB_DELETESTRING
CB_DELETESTRING
LB_GETCOUNT
CB_GETCOUNT
LB_GETCURSEL
CB_GETCURSEL
LB_GETTEXT
CB_GETLBTEXT
LB_SETCURSEL
CB_SETCURSEL
, Combo box,
MSDN.
.
. 7.12
.
7.12. Edit box, List box
Combo box
Edit box List box
Combo box
EN_SETFOCUS, LBN_SETFOCUS
CBN_SETFOCUS
EN_KILLFOCUS, LBN_KILLFOCUS
CBN_KILLFOCUS
EN_UPDATE
CBN_EDITUPDATE
EN_CHANGE
CBN_EDITCHANGE
EN_ERRSPACE, LBN_ERRSPACE
CBN_ERRSPACE
LBN_SELCHANGE
CBN_SELCHANGE
Combo box
.
. ,
.
359
Combo box.
, IDC_LIST1,
,
. ,
.
. ShiftWindow
, KWnd.
MyNotebook2.
MyNotebook1 (. 7.4) MyNotebook2
.cpp, .h .rc,
MyNotebook1 MyNotebook2. KWnd.h, KWnd.cpp,
KWnd, KWndPlut.h, KWndPlut.cpp1.
.
IDD_VIEW
Resource View Workspace.
(. 7.31) Static Text ( :) Combo box.
. 7.31.
360
7.
7.5 ()
//
//====================================================================
//
void ShiftWindow(HWND hwnd, int dX = 0, int dY = 0,
int dW = 0, int dH = 0);
//
void ShiftWindow(HWND hChild, HWND hParent, int dX = 0,
int dY = 0, int dW = 0, int dH = 0);
//
void ShiftWindow(int ctrlID, HWND hParent, int dX = 0,
int dY = 0, int dW = 0, int dH = 0);
//////////////////////////////////////////////////////////////////////
// KWndPlut.cpp
#include "KWndPlut.h"
KWnd::KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
LRESULT (WINAPI *pWndProc)(HWND,UINT,WPARAM,LPARAM),
LPCTSTR menuName, int x, int y, int width, int height,
UINT classStyle, DWORD windowStyle, HWND hParent)
{
/* 1.2 */
}
//====================================================================
//
//====================================================================
//
void ShiftWindow(HWND hwnd, int dX, int dY, int dW, int dH) {
RECT rect;
GetWindowRect(hwnd, &rect);
int x0 = rect.left + dX;
int y0 = rect.top + dY;
int width = rect.right - rect.left + dW;
int height = rect.bottom - rect.top + dH;
MoveWindow(hwnd, x0, y0, width, height, TRUE);
}
//
void ShiftWindow(HWND hChild, HWND hParent, int dX, int dY, int dW, int dH) {
RECT rect;
POINT p0;
GetWindowRect(hChild, &rect);
int width = rect.right - rect.left + dW;
int height = rect.bottom - rect.top + dH;
p0.x = rect.left + dX;
p0.y = rect.top + dY;
ScreenToClient(hParent, &p0);
MoveWindow(hChild, p0.x, p0.y, width, height, TRUE);
}
//
void ShiftWindow(int ctrlID, HWND hParent, int dX, int dY, int dW, int dH) {
RECT rect;
HWND hCtrl = GetDlgItem(hParent, ctrlID);
361
POINT p0;
GetWindowRect(hCtrl, &rect);
int width = rect.right - rect.left + dW;
int height = rect.bottom - rect.top + dH;
p0.x = rect.left + dX;
p0.y = rect.top + dY;
ScreenToClient(hParent, &p0);
ShowWindow(hCtrl, SW_HIDE);
MoveWindow(hCtrl, p0.x, p0.y, width, height, TRUE);
ShowWindow(hCtrl, SW_SHOW);
}
//////////////////////////////////////////////////////////////////////
// MyNotebook2.cpp
#include <windows.h>
#include <fstream>
using namespace std;
#include "KWndPlut.h"
#include "resource.h"
#define N1 21
#define N2 81
#define TOTAL_SIZE (3*N1 + N2)
fstream fdat;
struct SubStr {
/* 7.4 */
};
union Data {
/* 7.4 */
};
class ListItem {
/* 7.4 */
};
ListItem item;
int fontHeight[] = { 16, 20, 24, 28, 30 };
int iFont = 0; // List box
BOOL CALLBACK ViewDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK AddRecDiaProc(HWND, UINT, WPARAM, LPARAM);
void AdjustDialogSize(HWND hDlg);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("MyNotebook2", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
362
7.
7.5 ()
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* 7.4 */
}
//====================================================================
//
// ,
void AdjustDialogSize(HWND hDlg) {
int nCtrlId[] = { IDC_GROUP_1, IDC_STATIC_ADDR, IDC_STATIC_BDAY,
IDC_INFO_ADDR, IDC_INFO_BDAY, IDOK, IDCANCEL, IDC_REC_ADD,
IDC_REC_DELETE };
HWND hListBox = GetDlgItem(hDlg, IDC_LIST1);
static LOGFONT lf;
static HFONT hFont1;
HDC hDC;
TEXTMETRIC tm;
int showTextWidth; //
//
RECT rcLB;
//
int shift;
//
//
( ),
showTextWidth
// hListBox
if (hFont1) DeleteObject(hFont1);
lf.lfHeight = fontHeight[iFont];
lstrcpy( (LPSTR)&lf.lfFaceName, "Courier" );
hFont1 = CreateFontIndirect(&lf);
SendMessage(hListBox, WM_SETFONT, (WPARAM)hFont1, TRUE );
// ,
//
hDC = GetDC(hListBox);
SelectObject(hDC, hFont1);
GetTextMetrics(hDC, &tm);
ReleaseDC(hListBox, hDC);
GetWindowRect(hListBox, &rcLB);
showTextWidth = tm.tmAveCharWidth * 2 * N1 + 10;
shift = showTextWidth - (rcLB.right - rcLB.left);
ShiftWindow(hDlg, 0, 0, shift);
ShiftWindow(IDC_LIST1, hDlg, 0, 0, shift);
ShiftWindow(IDC_GROUP_0, hDlg, 0, 0, shift);
for (int i = 0; i < sizeof(nCtrlId) / sizeof(int); ++i)
ShiftWindow(nCtrlId[i], hDlg, shift);
ShiftWindow(IDC_STATIC_PHONE, hDlg, shift / 2);
}
363
//====================================================================
BOOL CALLBACK ViewDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
static HWND hListBox, hComboFont;
static HWND hEditInfoAddr, hEditInfoBday;
HWND hCtrl;
COLORREF editInfoColor;
static HBRUSH hBrush;
int nItems;
//
int iCurItem; //
BOOL dlgYes;
int i;
char buf[10];
switch (uMsg) {
case WM_INITDIALOG:
hListBox = GetDlgItem(hDlg, IDC_LIST1);
hComboFont = GetDlgItem(hDlg, IDC_COMBO_FONT);
hEditInfoAddr = GetDlgItem(hDlg, IDC_INFO_ADDR);
hEditInfoBday = GetDlgItem(hDlg, IDC_INFO_BDAY);
//
editInfoColor = RGB(190, 255, 255);
hBrush = CreateSolidBrush(editInfoColor);
//
AdjustDialogSize(hDlg);
//
for (i = 0; i < sizeof(fontHeight) / sizeof(int); ++i) {
sprintf(buf, "%d", fontHeight[i]);
SendMessage(hComboFont, CB_ADDSTRING, 0, (LPARAM)buf);
}
SendDlgItemMessage(hDlg, IDC_COMBO_FONT, CB_SETCURSEL, iFont, 0);
// " "
fdat.open("notebook.dat", ios::in);
if (!fdat) { fdat.clear(); return TRUE; }
else while (1) {
fdat.getline(item.dat.line, sizeof(Data));
if (fdat.eof()) { fdat.clear(); break; }
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)item.dat.line);
}
fdat.close();
return TRUE;
case WM_CTLCOLORSTATIC:
/* 7.4 */
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_REC_ADD:
/* 7.4 */
364
7.
7.5 ()
break;
case IDC_REC_DELETE:
/* 7.4 */
break;
case IDC_LIST1:
/* 7.4 */
break;
case IDOK:
/* 7.4 */
return TRUE;
case IDCANCEL:
EndDialog(hDlg, FALSE);
return TRUE;
case IDC_COMBO_FONT:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
//
iFont = SendMessage(hComboFont, CB_GETCURSEL, 0, 0);
//
AdjustDialogSize(hDlg);
return TRUE;
}
break;
}
break;
}
return FALSE;
}
//====================================================================
BOOL CALLBACK AddRecDiaProc(HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
/* 7.4 */
}
//////////////////////////////////////////////////////////////////////
CBN_SELCHANGE,
CB_GETCURSEL, ,
.
iFont. AdjustDialogSize,
.
. ,
hListBox. ,
hListBox ,
.
,
, .
AdjustDialogSize
ShiftWindow. ShiftWindow
365
KWndPlut.h,
KWndPlut.cpp.
ShiftWindow
(toplevel window).
hwnd .
hDlg.
ShiftWindow
.
HWND. .
.
, GetWindowRect ,
. MoveWindow
, ,
, .
ScreenToClient. ,
, , .
ShiftWindow
.
, int.
,
.
. 7.32 MyNotebook2,
Combo box 24 .
. 7.32. MyNotebook2. 24
, KWndPlut.h, KWndPlut.cpp
. KWnd
ShiftWindow.
,
. ,
.
.
366
7.
, .
, .
,
. ,
Find Replace,
.
,
. ,
.
.
,
DialogBox.
. CreateDialog.
, DialogBox:
hDlgModeless = CreateDialog(hInst, MAKEINTRESOURCE(IDD_DLG), hWnd, DlgProc);
,
,
.
, CreateDialog
. , .
,
Visible More Styles Dialog Properties. ,
CreateDialog
ShowWindow:
ShowWindow(hDlgModeless, SW_SHOW);
Visible
ShowWindow .
:
Visible.
,
,
.
WinMain
:
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(hModelessDlg, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
367
IsDialogMessage , ,
msg, hModelessDlg. ,
,
TRUE.
FALSE.
, ,
TranslateMessage DispatchMessage.
if, IsDialogMessage.
, ,
hModelessDlg IsDialogMessage
FALSE.
EndDialog
DestroyWindow. ,
, hModelessDlg
.
,
,
.
WM_CLOSE.
. , ,
:
case WM_CLOSE:
DestroyWindow(hDlg);
hModelessDlg = 0;
break;
Close (Alt+F4)
.
ModelessDlg, ,
, .
.
Win32 Application ModelessDlg.
KWndPlut.h, KWndPlut.cpp MyNotebook2,
.
c IDD_
MODELESS . Styles Dialog Properties
Child, More Styles Visible.
.
OK Cancel.
Red, Green Blue,
Vertical Scroll Bar (. 7.33).
, , IDC_RED,
IDC_GREEN, IDC_BLUE.
Visible Tab stop.
368
7.
. 7.33. IDD_MODELESS
ModelessDlg.cpp,
7.6.
7.6. ModelessDlg
//////////////////////////////////////////////////////////////////////
// ModelessDlg.cpp
#include <windows.h>
#include "KWndPlut.h"
#include "resource.h"
enum UserMsg { UM_CHANGE = WM_USER+1 };
HWND hModelessDlg;
RECT rcWork; //
int rgb[3]; // R-, G-, B-
BOOL CALLBACK ModelessDlgProc(HWND, UINT, WPARAM, LPARAM);
void AdjustDlgPlace(HWND, HWND);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("ModelessDlg", hInstance, nCmdShow, WndProc,
NULL, 100, 100, 400, 300);
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(hModelessDlg, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
369
{
switch (uMsg) {
case WM_CREATE:
hModelessDlg = CreateDialog(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_MODELESS), hWnd, ModelessDlgProc);
AdjustDlgPlace(hWnd, hModelessDlg);
break;
case WM_SIZE:
AdjustDlgPlace(hWnd, hModelessDlg);
break;
case UM_CHANGE:
//
SetClassLong(hWnd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(
RGB(rgb[0], rgb[1], rgb[2])));
InvalidateRect(hWnd, &rcWork, TRUE);
break;
case WM_DESTROY:
DestroyWindow(hModelessDlg);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
BOOL CALLBACK ModelessDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
HWND hCtrl;
int iCtrlID,
HWND hRvalue
HWND hGvalue
HWND hBvalue
iIndex;
= GetDlgItem(hDlg, IDC_RED);
= GetDlgItem(hDlg, IDC_GREEN);
= GetDlgItem(hDlg, IDC_BLUE);
switch (uMsg) {
case WM_INITDIALOG:
SetScrollRange(hRvalue, SB_CTL, 0, 255, FALSE);
SetScrollPos(hRvalue, SB_CTL, 0, FALSE);
SetScrollRange(hGvalue, SB_CTL, 0, 255, FALSE);
SetScrollPos(hGvalue, SB_CTL, 0, FALSE);
SetScrollRange(hBvalue, SB_CTL, 0, 255, FALSE);
SetScrollPos(hBvalue, SB_CTL, 0, FALSE);
return TRUE;
case WM_VSCROLL:
hCtrl = (HWND)lParam;
iCtrlID = GetDlgCtrlID(hCtrl);
370
7.
7.6 ()
iIndex = iCtrlID - IDC_RED;
switch(LOWORD(wParam)) {
case SB_LINEUP:
rgb[iIndex] = max(0, rgb[iIndex] - 1);
break;
case SB_LINEDOWN:
rgb[iIndex] = min(255, rgb[iIndex] + 1);
break;
case SB_PAGEUP:
rgb[iIndex] -= 15;
break;
case SB_PAGEDOWN:
rgb[iIndex] += 15;
break;
case SB_THUMBTRACK:
rgb[iIndex] = HIWORD(wParam);
break;
}
SetScrollPos(hCtrl, SB_CTL, rgb[iIndex], TRUE);
//
SendMessage(GetParent(hDlg), UM_CHANGE, 0, 0);
break;
}
return FALSE;
}
//====================================================================
void AdjustDlgPlace(HWND hParent, HWND hDlg) {
RECT rcParent, rcDlg;
// hDlg
GetClientRect(hParent, &rcParent);
GetWindowRect(hDlg, &rcDlg);
int width = rcDlg.right - rcDlg.left;
int height = rcDlg.bottom - rcDlg.top;
int dH = rcParent.bottom - height;
ShiftWindow(hDlg, hParent, 0, 0, 0, dH);
// hParent
rcWork = rcParent;
rcWork.left += width;
}
//////////////////////////////////////////////////////////////////////
hModelessDlg IDD_MODELESS
WndProc CreateDialog,
WM_CREATE.
AdjustDlgPlace,
,
.
ShiftWindow. , AdjustDlgPlace
,
, , .
371
rcWork WndProc
InvalidateRect,
.
ModelessDlgProc
IDC_RED, IDC_GREEN IDC_BLUE. Vertical
Scroll Bar ,
.
TextViewer (. 2.2).
rgb, RGB
. ,
SendMessage
UM_CHANGE, .
UM_CHANGE UserMsg,
enum.
WndProc UM_CHANGE.
SetClassLong
. ,
InvalidateRect. ,
InvalidateRect NULL,
.
WM_DESTROY.
: IDD_MODELESS Styles
Dialog Properties Popup, AdjustDlgPlace
ShiftWindow:
ShiftWindow(hDlg, 0, 0, 0, dH);
ModelessDlg . 7.34.
. 7.34. ModelessDlg
,
,
.
372
7.
, MessageBox,
.
,
.
MessageBox ,
. ,
, ,
.
MessageBox
.
printf .
. , ,
.
:
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
hWnd .
NULL, .
lpText C, ,
.
\n, .
lpCaption C,
. NULL,
Error.
uType .
,
. 7.137.15.
,
. 7.13.
7.13. ,
MB_CANCELTRYCONTINUE
MB_HELP
Help .
, WM_HELP
-
MB_OK
OK.
MB_OKCANCEL
OK Cancel
MB_RETRYCANCEL
Retry Cancel
MB_YESNO
Yes No
MB_YESNOCANCEL
OK, No Cancel
, ,
. 7.14.
373
7.14. ,
MB_ICONEXCLAMATION,
MB_ICONWARNING
MB_ICONINFORMATION,
MB_ICONASTERISK
MB_ICONQUESTION
MB_ICONSTOP,
MB_ICONERROR, MB_ICONHAND
, ,
. 7.15.
7.15. ,
MB_APPLMODAL
,
, hWnd. , hWnd
. popup,
, .
, MB_APPLMODAL,
, WS_EX_TOPMOST,
. ,
, MB_APPLMODAL,
, , hWnd NULL,
.
, - (,
)
MB_SYSTEMMODAL
MB_TASKMODAL
, ,
MSDN.
,
:
IDABORT
IDCANCEL
IDCONTINUE
IDIGNORE
IDNO
IDOK
IDRETRY
IDTRYAGAIN
IDYES
Yes
Abort
Abort Esc
Continue
Ignore
No
OK
Retry
Try Again
, .
MessageBox ,
.
374
7.
, Windows,
,
.
.
FileOpen ()
, .
.
Windows 3.1,
(Common Dialog Box Library).
,
, , ,
.
, ,
commdlg.h .
,
.
, .
,
.
.
CommonDialogs,
, , Open
(), Save As ( ), Color () Font ().
CommonDialogs.
IDR_MENU1.
, . 7.16.
7.16.
&File
&Background color
&Text color
IDM_BKGR_COLOR
IDM_TEXT_COLOR
&Choose font
IDM_CHOOSE_FONT
File , . 7.17.
7.17. File
&Open
Save &As
SEPARATOR
IDM_OPEN
IDM_SAVE_AS
E&xit
IDM_EXIT
CommonDialogs.cpp ,
7.7.
375
7.7. CommonDialogs
//////////////////////////////////////////////////////////////////////
// CommonDialogs.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "resource.h"
#define ESC_OF " "
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("CommonDialogs", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rcClient;
BOOL success;
static COLORREF textColor;
// "Open", "Save As"
static OPENFILENAME ofn;
static char szFile[MAX_PATH];
// "Color"
static CHOOSECOLOR cc; // common dialog box structure
static COLORREF acrCustClr[16]; // array of custom colors
// "Font"
static CHOOSEFONT chf;
static HFONT hFont;
static LOGFONT lf;
switch (uMsg)
{
case WM_CREATE:
// ofn
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
// cc
376
7.
7.7 ()
cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = hWnd;
cc.lpCustColors = (LPDWORD) acrCustClr;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
// chf
chf.lStructSize = sizeof(CHOOSEFONT);
chf.hwndOwner = hWnd;
chf.lpLogFont = &lf;
chf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT;
chf.nFontType = SIMULATED_FONTTYPE;
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_OPEN:
strcpy(szFile, "");
success = GetOpenFileName(&ofn);
if (success)
MessageBox(hWnd, ofn.lpstrFile, " :", MB_OK);
else
MessageBox(hWnd, ESC_OF"GetOpenFileName",
" ", MB_ICONWARNING);
break;
case IDM_SAVE_AS:
strcpy(szFile, "");
success = GetSaveFileName(&ofn);
if (success)
MessageBox(hWnd, ofn.lpstrFile,
" :", MB_OK);
else
MessageBox(hWnd, ESC_OF"GetSaveFileName",
" ", MB_ICONWARNING);
break;
case IDM_BKGR_COLOR:
if (ChooseColor(&cc))
SetClassLong(hWnd, GCL_HBRBACKGROUND,
(LONG)CreateSolidBrush(cc.rgbResult));
break;
case IDM_TEXT_COLOR:
if (ChooseColor(&cc)) textColor = cc.rgbResult;
break;
case IDM_CHOOSE_FONT:
if(ChooseFont(&chf)) hFont = CreateFontIndirect(chf.lpLogFont);
break;
case IDM_EXIT:
SendMessage(hWnd, WM_DESTROY, 0, 0);
break;
default:
break;
}
377
.
OPENFILENAME Open Save
As. CHOOSECOLOR Color,
CHOOSEFONT
Font. ofn, cc chf
static. :
,
,
WndProc.
ofn, cc chf
WM_CREATE.
. 7.35. CommonDialogs
378
7.
:
Open
GetOpenFileName
Save As
GetSaveFileName
Color
ChooseColor
Font
ChooseFont
379
Windows
. , Windows 95,
, .
, Microsoft
(common control library).
, ,
.
comctl32.dll.
, ,
, Windows Explorer
. . 8.18.4
.
8.1.
Toolbar ( )
Tooltip ( )
Status bar ( )
8.2.
Tab control ()
Property sheet
( )
, ,
Property page ( )
,
Property sheet
380
8.
Tree view ( )
(
Windows Explorer)
List view ( )
, (
Windows Explorer)
8.4.
Animation
( )
Header
( )
List view
Image list ( )
Progress bar
( )
Rich edit
( )
,
OLE-
Slider ()
, (
)
Spin ( )
, ,
,
.
.
CreateWindow,
.
.
,
.
.
WM_COMMAND,
WM_NOTIFY.
, InitCommonControlsEx,
381
.
:
BOOL InitCommonControlsEx(LPINITCOMMONCONTROLSEX lpInitCtrls);
lpInitCtrls
INITCOMMONCONTROLSEX, ,
.
INITCOMMONCONTROLSEX :
typedef struct tagINITCOMMONCONTROLSEX {
DWORD dwSize; //
DWORD dwICC;
// DLL
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
,
. 8.5.
8.5. InitCommonControlsEx
ICC_ANIMATE_CLASS
animate
ICC_BAR_CLASSES
ICC_LISTVIEW_CLASSES
ICC_PROGRESS_CLASS
progress bar
ICC_TAB_CLASSES
tab, tooltip
ICC_TREEVIEW_CLASSES
ICC_UPDOWN_CLASS
up-down
ICC_WIN95_CLASSES
animate, header, hot key, list view, progress bar, status bar, tab,
tooltip, toolbar, slider, tree view, up-down
MSDN.
InitCommonControlsEx ,
, commctrl.h.
, windows.h.
,
, :
#include <commctrl.h>
comctl32.lib. Visual Studio 6.0,
Object/library modules
, Project
SettingsLink.
,
:
error LNK2001: unresolved external symbol __imp__InitCommonControls@0
, InitCommonControlsEx,
, , , ,
. , ,
,
. !
382
8.
Rich edit
riched32.dll.
LoadLibrary:
LoadLibrary("riched32.dll");
,
,
#include <richedit.h>
CreateWindow CreateWindowEx. ,
:
HWND hwndToolBar = CreateWindow(TOOLBARCLASSNAME, NULL, WS_CHILD |
WS_VISIBLE | WS_BORDER, 0, 0, 16, 16, hwndParent, (HMENU)1, hInst, 0);
TOOLBARCLASSNAME ,
,
, . ANSI
TOOLBARCLASSNAME ToolbarWindow32,
UNICODE L"ToolbarWindow32".
.
, WS_CHILD
hwndParent.
CreateWindow
,
. ,
CreateToolbarEx.
.
. . 8.6
.
8.6.
Toolbar
TOOLBARCLASSNAME
CreateToolbarEx
Tooltip
TOOLTIPS_CLASS
Status bar
STATUSCLASSNAME
CreateStatusWindow
Tab control
WC_TABCONTROL
Property sheet
PropertySheet
383
Property page
Tree view
List view
Animation
Header
Image list
Progress bar
Rich edit
Slider
WC_TREEVIEW
WC_LISTVIEW
ANIMATE_CLASS
WC_HEADER
PROGRESS_CLASS
"RichEdit" (ANSI) L"RichEdit" (UNICODE)
TRACKBAR_CLASS
CreatePropertySheetPage
ImageList_Create
Spin
UPDOWN_CLASS
CreateUpDownControl
CreateWindow
.
:
( WS_)1, (WS_EX_)2,
(CCS_)
, .
CCS_. ,
. . 8.7
.
8.7.
CCS_ADJUSTABLE
.
Status bar
.
Tool bar
CCS_BOTTOM
CCS_NODIVIDER
CCS_NOMOVEY
CCS_NORESIZE
CCS_TOP
, ,
, . 8.8.
1
. 1.8 ( 1).
. 1.9 ( 1).
384
8.
8.8. ,
Toolbar
TBSTYLE_
Tooltip
TTS_
Status bar
SBARS_
Tab control
TCS_
Property sheet
Property page
Tree view
TVS_
List view
LVS_
Animation
ACS_
Header
HDS_
Image list
Progress bar
Rich edit
ES_
Slider
TBS_
Spin
UDS_
,
SendMessage.
.
, (Tree view)
hwndTV TVM_INSERTITEM.
SendMessage:
hItem = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM, 0,
(LPARAM)(LPTV_INSERTSTRUCT) &tvis);
SendMessage
, commctrl.h. ,
, TreeView_ InsertItem:
hItem = TreeView_InsertItem (hwndTV, &tvis);
, .
, Win32
. commctrl.h
Tab control, Tree view, List view,
Animation Header. prsht.h
Property sheet.
,
,
.
WM_COMMAND,
WM_NOTIFY.
385
. ,
, WM_NOTIFY
, WM_COMMAND,
. , ,
WM_COMMAND
.
Slider Spin, WM_VSCROLL WM_HSCROLL.
, ,
. . 8.9.
8.9.
NM_CLICK
NM_DBLCLK
NM_KILLFOCUS
NM_OUTOFMEMORY
NM_RCLICK
NM_RDBLCLK
NM_RETURN
Enter
NM_SETFOCUS
. , (Tab control)
.
, .
: Toolbar, Tooltip, Status
bar, Progress bar, Slider Spin.
: ,
. . 8.1 ,
MS Visual Studio 6.0.
,
.
, WM_COMMAND
.
,
386
8.
. ,
,
.
. 8.1. ,
.
,
. .
, ,
.
,
,
. ,
.
,
.
, . , ,
, .
TBSTYLE_SEP,
.
,
, , , , (combo box).
CreateWindow.
387
:
1. .
2. TBBUTTON,
.
3. CreateToolbarEx
.
ToolBar,
MenuDemo1,
6.
, .
ToolBar
ToolBar. MenuDemo1
(. 6.1) ToolBar .cpp, .h .rc,
MenuDemo1 ToolBar.
.
comctl32.lib .
Visual Studio 6.0 Link
Project Settings, ProjectSettings.
Visual Studio InsertResource.
Insert Resource Toolbar
New.
,
(. 8.2).
. 8.2.
IDR_TOOLBAR1.
, ResourceView Workspace
IDR_TOOLBAR1
Properties. Toolbar Properties
ID .
IDR_TOOLBAR1.
388
8.
, . 8.2,
.
.
,
.
16 15 .
.
Graphics,
, .
.
Toolbar Button Properties
. ,
, .
,
ID_RECTANGLE.
,
(. 8.3).
. 8.3.
,
, .
, .
ID_SEP ( ).
,
,
.
.
. ,
, . 8.4.
. 8.4.
11 ,
.
389
, . ,
. 8.10.
8.10. ,
ID_RECTANGLE
ID_RHOMB
ID_ELLIPSE
ID_SEP
ID_RED
ID_GREEN
ID_BLUE
ID_SEP
ID_DARK
ID_MEDIUM
10
ID_LIGHT
, , ,
.
,
.
,
toolbar1.bmp, .
.
ToolBar.rc ,
:
IDR_TOOLBAR1 TOOLBAR DISCARDABLE
BEGIN
BUTTON
ID_RECTANGLE
BUTTON
ID_RHOMB
END
16, 15
:
IDR_TOOLBAR1
BITMAP
DISCARDABLE
"toolbar1.bmp"
TBBUTTON
CreateToolbarEx,
TBBUTTON. TBBUTTON commctrl.h
:
typedef struct _TBBUTTON {
int iBitmap;
//
// - ( )
int idCommand;
//
BYTE fsState;
//
BYTE fsStyle;
//
DWORD dwData;
//
INT_PTR iString; // ( )
} TBBUTTON;
390
8.
.
fsState :
TBSTATE_CHECKED
TBSTYLE_CHECK
TBSTATE_PRESSED
TBSTATE_ENABLED
( )
TBSTATE_HIDDEN
( )
TBSTATE_INDETERMINATE
fsStyle :
TBSTYLE_BUTTON
. ,
TBSTYLE_SEP
TBSTYLE_CHECK
, (check box).
( / )
TBSTYLE_GROUP
(radio button)
TBSTYLE_CHECKGROUP
TBSTYLE_CHECK TBSTYLE_GROUP
dwData .
,
. ,
TB_GETBUTTON.
iString ,
.
, TB_ADDSTRING.
, CreateToolbarEx,
TBBUTTON:
TBBUTTON tbb[NUM_BUTTONS];
CreateToolbarEx
CreateToolbarEx,
, :
HWND CreateToolbarEx(
HWND hwnd,
DWORD ws,
UINT wID,
int nBitmaps,
HINSTANCE hBMInst,
//
//
//
//
// ,
//
UINT wBMID,
//
LPCTBBUTTON lpButtons, // TBBUTTON
int iNumButtons,
//
int dxButton,
//
int dyButton,
//
int dxBitmap,
int dyBitmap,
UINT uStructSize
391
//
//
// TBBUTTON
);
ws.
WS_CHILD WS_VISIBLE.
, WS_BORDER. , ,
. , TBSTYLE_TOOLTIPS,
.
TBSTYLE_WRAPABLE. ,
.
, . 8.7. ,
CCS_TOP.
wID .
,
, ,
resource.h.
dxButton dyButton
, dxBitmap dyBitmap
. ,
.
: dxButton=16, dyButton=16, dxBitmap=16, dyBitmap=15. Windows
, , dxButton+7
dyButton+6 .
,
.
, .
,
.
TB_AUTOSIZE
, .
WM_SIZE:
SendMessage(hwndToolBar, TB_AUTOSIZE, 0, 0);
(. . 8.7). , CCS_TOP
. ,
CCS_NORESIZE
.
(Tooltip) , .
, (hot)
, ,
.
Tooltip ,
(tool).
392
8.
.
:
Tooltip,
CreateWindowEx TOOLTIPS_CLASS;
Tooltip, .
. .
, .
TBSTYLE_TOOLTIPS,
, ,
. , WM_NOTIFY
WM_NEEDTEXT.
, ,
.
WM_NOTIFY lParam
TOOLTIPTEXT, :
typedef struct {
NMHDR
hdr;
LPTSTR
lpszText;
WCHAR
szText[80];
HINSTANCE hinst;
UINT
uflags;
} TOOLTIPTEXT;
//
//
//
//
//
//
hdr NMHDR,
WM_NOTIFY. ,
, :
typedef struct tagNMHDR {
HWND hwndFrom; //
UINT idFrom;
//
UINT code;
//
} NMHDR;
WM_NOTIFY,
lParam lpTTT LPTOOLTIPTEXT,
lpTTT->hdr.code. TTN_NEEDTEXT,
. ,
, lpTTT->hdr.idFrom.
,
.
TOOLTIPTEXT
:
1. lpTTT->szText.
2. , , lpTTT->lpszText.
3. , ,
lpTTT->lpszText ,
, lpTTT->hinst.
393
switch,
lpTTT->hdr.idFrom.
.
.
1 ,
,
switch case. WM_NOTIFY
:
case WM_NOTIFY:
lpTTT = (LPTOOLTIPTEXT)lParam;
if (lpTTT->hdr.code == TTN_NEEDTEXT) {
lpTTT->hinst = GetModuleHandle(NULL);
lpTTT->lpszText = MAKEINTRESOURCE(lpTTT->hdr.idFrom);
}
break;
lpTTT->hdr.idFrom.
.
, ToolBar.
ToolBar
.
:
ID_RECTANGLE
ID_RHOMB
ID_ELLIPSE
ID_RED
ID_GREEN
ID_BLUE
ID_DARK
ID_MEDIUM
ID_LIGHT
ToolBar.cpp
MenuDemo1.cpp. , 8.1.
8.1. ToolBar
//////////////////////////////////////////////////////////////////////
// ToolBar.cpp
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "KWnd.h"
5.
394
8.
8.1 ()
#include "resource.h"
#define W 200
//
#define H 140
//
enum ShapeSize { MAX, MIN };
typedef struct {
int id_shape;
BOOL fRed;
BOOL fGreen;
BOOL fBlue;
int id_bright;
} ShapeData;
//
//
//
//
//
}
//====================================================================
HWND InitToolBar(HWND hWnd) {
HWND hToolBar;
int btnID[NUM_BUTTONS] = { ID_RECTANGLE, ID_RHOMB, ID_ELLIPSE, ID_SEP,
ID_RED, ID_GREEN, ID_BLUE, ID_SEP, ID_DARK, ID_MEDIUM, ID_LIGHT };
int btnStyle[NUM_BUTTONS] = { TBSTYLE_BUTTON, TBSTYLE_BUTTON,
TBSTYLE_BUTTON, TBSTYLE_SEP, TBSTYLE_CHECK, TBSTYLE_CHECK,
TBSTYLE_CHECK, TBSTYLE_SEP, TBSTYLE_CHECKGROUP, TBSTYLE_CHECKGROUP,
TBSTYLE_CHECKGROUP };
TBBUTTON tbb[NUM_BUTTONS];
395
memset(tbb, 0, sizeof(tbb));
for (int i = 0; i < NUM_BUTTONS; ++i) {
if (btnID[i] == ID_SEP)
tbb[i].iBitmap = SEPARATOR_WIDTH;
else tbb[i].iBitmap = i;
tbb[i].idCommand = btnID[i];
tbb[i].fsState = TBSTATE_ENABLED;
tbb[i].fsStyle = btnStyle[i];
}
hToolBar = CreateToolbarEx(hWnd,
WS_CHILD | WS_VISIBLE | WS_BORDER | TBSTYLE_TOOLTIPS,
ID_TOOLBAR, NUM_BUTTONS, GetModuleHandle(NULL), IDR_TOOLBAR1,
tbb, NUM_BUTTONS, 0, 0, 0, 0, sizeof(TBBUTTON));
return hToolBar;
}
//====================================================================
void UpdateToolBar(ShapeData& sd) {
SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_RED, sd.fRed);
SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_GREEN, sd.fGreen);
SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_BLUE, sd.fBlue);
SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_DARK,
(sd.id_bright == ID_DARK));
SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_MEDIUM,
(sd.id_bright == ID_MEDIUM));
SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_LIGHT,
(sd.id_bright == ID_LIGHT));
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
static HMENU hMenu; //
int x0, y0, x1, y1, x2, y2;
POINT pt[4];
static ShapeSize shapeSize = MIN;
static BOOL bShow = TRUE;
static HBRUSH hBrush, hOldBrush;
char* itemResizeName[2] = { "Decrease!", "Increase!"};
int intensity[3] = { 85, 170, 255 }; // RGB-
int brightness;
static ShapeData shapeData;
RECT rcTB;
// hwndToolBar
int tbHeight; // hwndToolBar
LPTOOLTIPTEXT lpTTT;
switch (uMsg)
{
case WM_CREATE:
hMenu = GetMenu(hWnd);
SetMenuDefaultItem(GetSubMenu(hMenu, 0), IDM_OPEN, FALSE);
396
8.
8.1 ()
CheckMenuRadioItem(GetSubMenu(hMenu, 1), IDM_SHOW_SHAPE,
IDM_HIDE_SHAPE, IDM_SHOW_SHAPE, MF_BYCOMMAND);
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_RECTANGLE,
ID_ELLIPSE, ID_RECTANGLE, MF_BYCOMMAND);
CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_DARK,
ID_LIGHT, ID_DARK, MF_BYCOMMAND);
shapeData.id_shape = ID_RECTANGLE;
shapeData.id_bright = ID_DARK;
//
hwndToolBar = InitToolBar(hWnd);
SendMessage(hwndToolBar, TB_AUTOSIZE, 0, 0);
break;
//
case WM_SIZE:
SendMessage(hwndToolBar, TB_AUTOSIZE, 0, 0);
break;
//
case WM_NOTIFY:
lpTTT = (LPTOOLTIPTEXT)lParam;
if (lpTTT->hdr.code == TTN_NEEDTEXT) {
lpTTT->hinst = GetModuleHandle(NULL);
lpTTT->lpszText = MAKEINTRESOURCE(lpTTT->hdr.idFrom);
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
/* 6.1 */
}
UpdateToolBar(shapeData); //
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
brightness = intensity[shapeData.id_bright - ID_DARK];
if (bShow) {
hBrush = CreateSolidBrush(RGB(
shapeData.fRed? brightness : 0,
shapeData.fGreen? brightness : 0,
shapeData.fBlue? brightness : 0));
hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
// (x0, y0)
GetClientRect(hWnd, &rect);
//
// -
//
GetWindowRect(hwndToolBar, &rcTB);
tbHeight = rcTB.bottom - rcTB.top;
x0 = rect.right / 2;
397
( MenuDemo1) :
InitToolBar UpdateToolBar.
InitToolBar
hToolBar. tbb TBBUTTON for.
, TBSTYLE_BUTTON,
TBSTYLE_CHECK, TBSTYLE_CHECKGROUP.
tbb[i].iBitmap , ,
.
SEPARATOR_WIDTH.
CreateToolbarEx
TBSTYLE_TOOLTIPS,
.
ID_TOOLBAR, , #define.
InitToolBar WndProc
WM_CREATE.
398
8.
, TBSTYLE_CHECK TBSTYLE_
CHECKGROUP, . ,
.
,
,
. UpdateToolBar,
TB_CHECKBUTTON. UpdateToolBar
WM_COMMAND.
WM_SIZE,
TB_AUTOSIZE,
.
InitToolBar. ,
. TBSTYLE_WRAPABLE,
.
WM_NOTIFY,
.
.
"".
WM_PAINT ,
.
. 8.5 ToolBar.
. 8.5. ToolBar
,
. Toolbar
, ,
TB_ADDSTRING. , tbb
tbb[i].iString ( ,
).
399
, ,
. ToolBarWithText.
ToolBar (. 8.1) ToolBarWithText
.cpp, .h .rc, ToolBar
ToolBarWithText. toolbar1.bmp.
. Link
comctl32.lib.
ToolBarWithText.cpp ,
8.2.
8.2. ToolBarWithText
//////////////////////////////////////////////////////////////////////
// ToolBarWithText.cpp
/* , 8.1
*/
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("ToolBarWithText", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 430, 300);
/* , 8.1 */
return msg.wParam;
}
//====================================================================
HWND InitToolBar(HWND hWnd) {
/* hToolBar btnID btnStyle
8.1 */
TBBUTTON tbb[NUM_BUTTONS];
memset(tbb, 0, sizeof(tbb));
for (int i = 0; i < NUM_BUTTONS; ++i) {
if (btnID[i] == ID_SEP)
tbb[i].iBitmap = SEPARATOR_WIDTH;
else tbb[i].iBitmap = i;
tbb[i].idCommand
tbb[i].fsState =
tbb[i].fsStyle =
tbb[i].iString =
= btnID[i];
TBSTATE_ENABLED;
btnStyle[i];
i; //
}
hToolBar = CreateToolbarEx(hWnd,
WS_CHILD | WS_VISIBLE | WS_BORDER | TBSTYLE_TOOLTIPS,
ID_TOOLBAR, NUM_BUTTONS, GetModuleHandle(NULL), IDR_TOOLBAR1,
tbb, NUM_BUTTONS, 0, 0, 0, 0, sizeof(TBBUTTON));
// Toolbar
400
8.
8.2 ()
const char* str[NUM_BUTTONS] = { "Rect", "Rhomb", "Ellips", "",
"Red", "Green", "Blue", "", "Dark", "Medium", "Light" };
for (i = 0; i < NUM_BUTTONS; ++i)
SendMessage(hToolBar, TB_ADDSTRING, 0, (LPARAM)str[i]);
return hToolBar;
}
//====================================================================
void UpdateToolBar(ShapeData& sd) {
/* , 8.1 */
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* , 8.1 */
}
//////////////////////////////////////////////////////////////////////
InitToolBar.
tbb tbb[i].iString = i.
str.
IDR_TOOLBAR1, str
, .
. 8.6.
. 8.6. ToolBarWithText
. 8.7. TBSTYLE_LIST
401
.
. , CreateToolbarEx
TBSTYLE_LIST.
. 8.7.
,
.
, .
CreateToolbarEx TBSTYLE_LIST,
TBSTYLE_WRAPABLE,
,
.
. 8.8.
,
.
(combo box).
: ) ;
) ; )
.
, . ,
tbb[i].iBitmap. ,
.
WM_COMMAND .
( Windows)
402
8.
,
, .
WM_COMMAND WndProc
.
,
.
. ,
Tooltip.
ComboInToolbar,
ToolBar.
, (
1 ).
ComboInToolbar.
ToolBar (. 8.1) ComboInToolbar
.cpp, .h .rc, ToolBar ComboInToolbar.
toolbar1.bmp. .
Link comctl32.lib.
ResourceView Workspace
IDR_TOOLBAR1.
ID_SEP.
ComboInToolbar.cpp ,
8.3.
8.3. ComboInToolbar
//////////////////////////////////////////////////////////////////////
// ComboInToolBar.cpp
/* #include #define, ShapeSize ShapeData
8.1 */
#define
#define
#define
#define
#define
#define
ID_TOOLBAR
201
IDC_TB_COMBOBOX
202
NUM_BUTTONS
13
SEPARATOR_WIDTH
10
COMBO_SPACE_WIDTH
50
COMBO_SPACE_HEIGHT 100
HWND hwndToolBar;
HWND hwndCombo;
HWND InitToolBar(HWND hWnd);
void UpdateToolBar(ShapeData& sd);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
403
KWnd mainWnd("ComboInToolBar", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
/* , 8.1 */
return msg.wParam;
}
//====================================================================
HWND InitToolBar(HWND hWnd) {
HWND hToolBar;
int btnID[NUM_BUTTONS] = { ID_SEP, ID_SEP, ID_RECTANGLE, ID_RHOMB,
ID_ELLIPSE, ID_SEP, ID_RED, ID_GREEN, ID_BLUE, ID_SEP,
ID_DARK, ID_MEDIUM, ID_LIGHT };
int btnStyle[NUM_BUTTONS] = { TBSTYLE_SEP, TBSTYLE_SEP,
TBSTYLE_BUTTON, TBSTYLE_BUTTON, TBSTYLE_BUTTON, TBSTYLE_SEP,
TBSTYLE_CHECK, TBSTYLE_CHECK, TBSTYLE_CHECK, TBSTYLE_SEP,
TBSTYLE_CHECKGROUP, TBSTYLE_CHECKGROUP, TBSTYLE_CHECKGROUP };
TBBUTTON tbb[NUM_BUTTONS];
memset(tbb, 0, sizeof(tbb));
for (int i = 0; i < NUM_BUTTONS; ++i) {
if (!i) tbb[i].iBitmap = COMBO_SPACE_WIDTH;
else if (btnID[i] == ID_SEP)
tbb[i].iBitmap = SEPARATOR_WIDTH;
else tbb[i].iBitmap = i;
tbb[i].idCommand = btnID[i];
tbb[i].fsState = TBSTATE_ENABLED;
tbb[i].fsStyle = btnStyle[i];
}
hToolBar = CreateToolbarEx(hWnd,
WS_CHILD | WS_VISIBLE | WS_BORDER | TBSTYLE_TOOLTIPS,
ID_TOOLBAR, NUM_BUTTONS, GetModuleHandle(NULL), IDR_TOOLBAR1,
tbb, NUM_BUTTONS, 0, 0, 0, 0, sizeof(TBBUTTON));
// Combo box
int x, y, cx, cy;
RECT rcItem;
SendMessage(hToolBar, TB_GETITEMRECT, 0, (LPARAM)&rcItem);
x = rcItem.left + 2;
y = rcItem.top;
cx = COMBO_SPACE_WIDTH; cy = COMBO_SPACE_HEIGHT;
// Combo box
hwndCombo = CreateWindow("combobox", NULL, WS_CHILD | WS_VISIBLE |
CBS_DROPDOWN, x, y, cx, cy, hToolBar, (HMENU)IDC_TB_COMBOBOX,
GetModuleHandle(NULL), 0);
// hwndCombo
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)"
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)"
1
2
");
");
404
8.
8.3 ()
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)" 5
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)" 10
SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
");
");
return hToolBar;
}
//====================================================================
void UpdateToolBar(ShapeData& sd) {
/* , 8.1 */
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* 8.1 */
static HPEN hPen, hOldPen;
static int indPen;
int penWidth[] = { 1, 2, 5, 10 };
switch (uMsg)
{
case WM_CREATE:
/* , 8.1 */
break;
case WM_SIZE:
SendMessage(hwndToolBar, TB_AUTOSIZE, 0, 0);
break;
case WM_NOTIFY:
/* , 8.1 */
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
/* IDM_OPEN, IDM_CLOSE, , IDM_RESIZE
8.1 */
case IDM_ABOUT:
MessageBox(hWnd,
"ComboInToolBar\nVersion 1.0\nCopyright: "
"Finesoft Corporation, 2005.",
"About ComboInToolBar", MB_OK);
break;
//
case IDC_TB_COMBOBOX:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
//
indPen = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
}
405
break;
default:
break;
}
UpdateToolBar(shapeData);
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
brightness = intensity[shapeData.id_bright - ID_DARK];
if (bShow) {
hPen = CreatePen(PS_SOLID, penWidth[indPen], RGB(0,0,0));
hOldPen = (HPEN)SelectObject(hDC, hPen);
/* , 8.1 */
DeleteObject(SelectObject(hDC, hOldBrush));
DeleteObject(SelectObject(hDC, hOldPen));
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
, .
, COMBO_SPACE_WIDTH,
.
.
, btnID btnStyle
. btnID ID_SEP,
btnStyle TBSTYLE_SEP.
, , CreateToolbarEx.
. ,
, ,
TB_GETITEMRECT. rcItem
.
(x, y) .
406
8.
hwndCombo
CreateWindow.
CB_ADDSTRING.
WndProc .
:
static HPEN hPen, hOldPen;
static int indPen;
int penWidth[] = { 1, 2, 5, 10 };
CBN_SELCHANGE
:
case IDC_TB_COMBOBOX:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
//
indPen = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
}
break;
WM_PAINT
hPen:
hPen = CreatePen(PS_SOLID, penWidth[indPen], RGB(0,0,0));
hOldPen = (HPEN)SelectObject(hDC, hPen);
. 8.9 ComboInToolbar
10.
. 8.9. ComboInToolbar. 10
, ,
, ,
. ,
Tooltip.
Tooltip,
Tooltip
TOOLTIPS_CLASS CreateWindowEx.
, ,
Tooltip.
407
, :
hwndTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hwndOwner, NULL, hInst, NULL);
SendMessage
ti TOOLINFO. TOOLINFO :
typedef struct tagTOOLINFO {
UINT
cbSize;
//
UINT
uFlags;
//
HWND
hwnd;
// ,
WPARAM
uId;
//
RECT
rect;
//
HINSTANCE hinst;
// ,
//
LPTSTR
lpszText; // C-
//
#if (_WIN32_IE >= 0x0300)
PARAM lParam;
// 32- ,
//
#endif
} TOOLINFO, FAR* LPTOOLINFO;
uFlags ,
. 8.11.
8.11. uFlags
TTF_CENTERTIP
TTF_IDISHWND
, uId .
, uId
TTF_SUBCLASS
,
, WM_MOUSEMOVE
TTF_IDISHWND , uId
. ,
.
408
8.
lpszText ,
,
.
, Tooltip
, .
. .
KWnd KWndEx
, ,
, .
.
KWnd
KWndEx.
,
. , KWndEx.h,
KWndEx.cpp
.
:
ShiftWindow,
( 7.5);
AddTooltip, ;
TRACE,
Output ( TRACE MFC).
, !
ToolTip.
ComboInToolbar (. 8.3) ToolTip
.cpp, .h .rc, ComboInToolbar ToolTip.
toolbar1.bmp. Kwnd.h, Kwnd.cpp
KwndEx.h KwndEx.cpp .
. Link
comctl32.lib.
ResourceView Workspace.
String table
String table. :
IDS_TB_COMBOBOX
IDS_EDIT_IN_COMBO
, ,
Combo box .
,
,
.
KwndEx.h, KwndEx.cpp, ToolTip.cpp ,
8.4.
409
8.4. ToolTip
//////////////////////////////////////////////////////////////////////
// KWndEx.h
#include <windows.h>
class KWndEx {
public:
KWndEx(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
LRESULT (WINAPI *pWndProc)(HWND,UINT,WPARAM,LPARAM),
LPCTSTR menuName = NULL,
int x = CW_USEDEFAULT, int y = 0,
int width = CW_USEDEFAULT, int height = 0,
UINT classStyle = CS_HREDRAW | CS_VREDRAW,
DWORD windowStyle = WS_OVERLAPPEDWINDOW,
HWND hParent = NULL);
HWND GetHWnd() { return hWnd; }
protected:
HWND hWnd;
WNDCLASSEX wc;
};
//====================================================================
//
//-------------------------------------------------------------------//
//
void ShiftWindow(HWND hwnd, int dX = 0, int dY = 0,
int dW = 0, int dH = 0);
//
void ShiftWindow(HWND hChild, HWND hParent, int dX = 0,
int dY = 0, int dW = 0, int dH = 0);
//
void ShiftWindow(int ctrlID, HWND hParent, int dX = 0,
int dY = 0, int dW = 0, int dH = 0);
//-------------------------------------------------------------------//
void AddTooltip (HWND hwndOwner, LPTSTR lpMsg);
//-------------------------------------------------------------------// ( "Output")
//
- TRACE MFC
void TRACE(LPCTSTR lpszFormat, ...);
//////////////////////////////////////////////////////////////////////
// KWndEx.cpp
#include "KWndEx.h"
#include <commctrl.h>
KWndEx::KWndEx(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
LRESULT (WINAPI *pWndProc)(HWND,UINT,WPARAM,LPARAM),
LPCTSTR menuName, int x, int y, int width, int height,
UINT classStyle, DWORD windowStyle, HWND hParent)
{
/* , KWnd ( 1.2)
// "Common Control Library"
*/
410
8.
8.4 ()
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
icc.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&icc);
}
//====================================================================
//
//-------------------------------------------------------------------//
void ShiftWindow(HWND hwnd, int dX, int dY, int dW, int dH) {
/* 7.5 ( KWndPlut.cpp) */
}
//
void ShiftWindow(HWND hChild, HWND hParent, int dX, int dY, int dW, int dH) {
/* 7.5
*/
}
//
void ShiftWindow(int ctrlID, HWND hParent, int dX, int dY, int dW, int dH) {
/* 7.5 */
}
//-------------------------------------------------------------------//
void AddTooltip (HWND hwndOwner, LPTSTR lpMsg) {
HWND hwndTip;
// Tooltip
static TOOLINFO ti;
// ( ),
// hwndTip
HINSTANCE hInst = (HINSTANCE)GetWindowLong(hwndOwner, GWL_HINSTANCE);
hwndTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hwndOwner, NULL, hInst, NULL);
// ti
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS;
ti.hwnd = hwndOwner;
ti.hinst = hInst;
ti.uId = 0;
ti.lpszText = lpMsg;
// hwndOwner
// ( )
GetClientRect (hwndOwner, &ti.rect);
// ti
SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO) &ti);
}
//--------------------------------------------------------------------
411
// ( TRACE MFC)
#define N 512
void TRACE(LPCTSTR szFormat, ...)
{
va_list args;
va_start(args, szFormat);
int nBuf;
char szBuffer[N];
nBuf = _vsnprintf(szBuffer, N, szFormat, args);
if (nBuf < 0) {
MessageBox(NULL, " TRACE!",
"", MB_OK | MB_ICONSTOP);
szBuffer[N-2] = '\n';
szBuffer[N-1] = 0;
}
OutputDebugString(szBuffer);
va_end(args);
}
//////////////////////////////////////////////////////////////////////
// ToolTip.cpp
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "KWndEx.h"
#include "resource.h"
/* , 8.3 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWndEx mainWnd("ToolTip", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
//
AddTooltip (mainWnd.GetHWnd(),
" ");
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
412
8.
8.4 ()
HWND InitToolBar(HWND hWnd) {
/* , 8.3 */
//
AddTooltip (hwndCombo, MAKEINTRESOURCE(IDS_TB_COMBOBOX));
HWND hwndEdit = GetWindow(hwndCombo, GW_CHILD);
AddTooltip (hwndEdit, MAKEINTRESOURCE(IDS_EDIT_IN_COMBO));
return hToolBar;
}
//====================================================================
void UpdateToolBar(ShapeData& sd) {
/* , 8.3 */
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* , 8.3, :
case IDM_ABOUT:
MessageBox(hWnd,
"ToolTip\nVersion 1.0\nCopyright: Finesoft Corporation, 2005.",
"About ToolTip", MB_OK);
break;
*/
}
//////////////////////////////////////////////////////////////////////
:
KWndEx.h KWndEx.cpp KWndEx,
.
KWndEx KWnd .
InitCommonControlsEx,
.
AddTooltip, :
void AddTooltip (HWND hwndOwner, LPTSTR lpMsg);
Tooltip hwndOwner.
,
.
Tooltip
hwndOwner, AddTooltip
,
hwndOwner.
AddTooltip WinMain:
AddTooltip (mainWnd.GetHWnd(),
" ");
InitToolBar:
AddTooltip (hwndCombo, MAKEINTRESOURCE(IDS_TB_COMBOBOX));
HWND hwndEdit = GetWindow(hwndCombo, GW_CHILD);
AddTooltip (hwndEdit, MAKEINTRESOURCE(IDS_EDIT_IN_COMBO));
413
, .
TRACE, :
void TRACE(LPCTSTR szFormat, ...)
Output.
,
printf .
OutputDebugString.
, MFC,
TRACE . ,
Win32 API . ,
KwndEx.h KwndEx.cpp, !
, .
, (Win32
Debug). ,
Start DebugGo F5.
,
.
TRACE.
WM_NOTIFY :
TRACE("uMsg = %04X, wParam = %08X, lParam = %08X\n", uMsg, wParam, lParam);
, , TRACE
Output uMsg, wParam lParam
WM_NOTIFY.
:
uMsg = 004E, wParam
uMsg = 004E, wParam
uMsg = 004E, wParam
. . . . . . . . . .
=
=
=
.
(status bar) ,
,
.
.
,
.
CreateStatusWindow:
hwndStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWndParent,
ID_STATUS_BAR);
CreateWindow,
hWndParent,
ID_STATUS_BAR ,
. .
414
8.
CCS_BOTTOM
(. . 8.7) SBARS_SIZEGRIP. SBARS_SIZEGRIP
.
,
.
:
, , (MultiplePart Status Bars),
().
.
fMode TRUE, .
FALSE
() .
,
SB_SETPARTS:
SendMessage(hwndStatusBar, SB_SETPARTS, nParts, (LPARAM)aWidths);
nParts , aWidths
, (
) . aWidths
1,
.
.
, (Progress bar).
,
SB_GETRECT:
SendMessage(hwndStatusBar, SB_GETRECT, iPart, (LPARAM)&rect);
SB_SETTEXT:
SendMessage(hwndStatusBar, SB_SETTEXT, wParam, (LPARAM)szText);
415
uType :
uType
0 ( )
SBT_NOBORDERS
SBT_POPOUT
SBT_OWNERDRAW
, , 127
.
.
.
,
.
, WM_SIZE.
, ,
WM_SIZE, WndProc
, wParam lParam:
SendMessage (hwndStatusBar, WM_SIZE, wParam, lParam);
,
, SB_SETMINHEIGHT:
SendMessage(hwndStatusBar, SB_SETMINHEIGHT, minHeight, 0);
minHeight .
Windows , minHeight +
+ 2*wVB, wVB .
,
(.
ProgressBar).
,
. , Windows
. ToolBar
, ,
tbHeight.
, .
, Windows, ,
.
WM_MENUSELECT,
416
8.
.
.
WM_MENUSELECT,
:
wParam ,
, ( ).
wParam ,
.
MF_POPUP, ,
.
lParam ,
.
Win32 API MenuHelp,
WM_MENUSELECT .
[1]. , ,
.
, MenuHelp .
,
.
.
.
, .
,
.
, ,
. ,
, .
, ,
. Windows
.
-
, ,
, Windows, 0, 1, 2
. . wParam
WM_MENUSELECT.
, ,
itemID,
wParam,
:
itemID += 100 * (submenuID + 1);
submenuID .
417
, (submenuID=0)
100, 101, 102 . .
200, 201, 202 . .
.
,
()
.
WM_MENUSELECT
itemID,
text,
, .
:
SendMessage(hwndStatusBar, SB_SIMPLE, TRUE, 0);
LoadString(GetModuleHandle(NULL), itemID, text, 200);
SendMessage(hwndStatusBar, SB_SETTEXT, 255, (LPARAM)text);
StatusBar,
ToolBar.
,
.
StatusBar
StatusBar. ToolBar
(. 8.1) StatusBar ToolBar.cpp, ToolBar.rc resource.h,
ToolBar StatusBar.
toolbar1.bmp. , ToolTip
(. 8.4) KWndEx.h KWndEx.cpp.
.
Link comctl32.lib.
ResourceView Workspace.
String table
String table.
:
0
1
2
300
301
IDM_OPEN
IDM_CLOSE
IDM_SAVE
IDM_EXIT
IDM_SHOW_SHAPE
IDM_HIDE_SHAPE
IDM_RESIZE
IDM_ABOUT
418
8.
0, 1, 2, 300, 301,
.
StatusBar.cpp ,
8.5.
8.5. StatusBar
//////////////////////////////////////////////////////////////////////
// StatusBar.cpp
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "KWndEx.h"
#include "resource.h"
#define W 200 //
#define H 140 //
enum ShapeSize { MAX, MIN };
typedef struct {
int id_shape;
BOOL fRed;
BOOL fGreen;
BOOL fBlue;
int id_bright;
} ShapeData;
#define
#define
#define
#define
//
//
//
//
//
ID_TOOLBAR 201
ID_STATUSBAR 202
NUM_BUTTONS 11
SEPARATOR_WIDTH 10
#define N_PARTS 4
HWND hwndToolBar;
HWND hwndStatusBar;
HWND InitToolBar(HWND hWnd);
void UpdateToolBar(ShapeData& sd);
void UpdateStatusBar(HWND hwnd, ShapeData& sd);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWndEx mainWnd("StatusBar", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
/* , 8.1 */
}
//====================================================================
HWND InitToolBar(HWND hWnd) {
/* , 8.1 */
}
//====================================================================
419
void UpdateToolBar(ShapeData& sd) {
/* , 8.1 */
}
//====================================================================
void UpdateStatusBar(HWND hwnd, ShapeData& sd) {
int paneWidth;
int aWidths[N_PARTS];
char text[100];
RECT rect;
int brightness;
int intensity[3] = { 85, 170, 255 };
GetClientRect(hwnd, &rect);
paneWidth = rect.right / N_PARTS;
aWidths [0] = paneWidth;
aWidths [1] = paneWidth * 2;
aWidths [2] = paneWidth * 3;
aWidths [3] = -1;
SendMessage(hwndStatusBar, SB_SETPARTS, N_PARTS, (LPARAM)aWidths);
LoadString(GetModuleHandle(NULL), sd.id_shape, text, 100);
SendMessage(hwndStatusBar, SB_SETTEXT, 0, (LPARAM)text);
brightness = intensity[sd.id_bright - ID_DARK];
int red = sd.fRed? brightness : 0;
sprintf(text, "Red = %d", red);
SendMessage(hwndStatusBar, SB_SETTEXT, 1, (LPARAM)text);
int green = sd.fGreen? brightness : 0;
sprintf(text, "Green = %d", green);
SendMessage(hwndStatusBar, SB_SETTEXT, 2, (LPARAM)text);
int blue = sd.fBlue? brightness : 0;
sprintf(text, "Blue = %d", blue);
SendMessage(hwndStatusBar, SB_SETTEXT, 3, (LPARAM)text);
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* 8.1 */
RECT rcSB;
// hwndStatusBar
int sbHeight; // hwndStatusBar
HMENU hClickMenu;
int itemID;
static UINT submenuID;
char text[200];
switch (uMsg)
{
case WM_CREATE:
/* , 8.1 */
//
420
8.
8.5 ()
hwndStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd,
ID_STATUSBAR);
break;
case WM_SIZE:
SendMessage(hwndToolBar, TB_AUTOSIZE, 0, 0);
UpdateStatusBar(hWnd, shapeData);
SendMessage (hwndStatusBar, WM_SIZE, wParam, lParam);
break;
case WM_NOTIFY:
/* , 8.1 */
break;
case WM_MENUSELECT:
itemID = LOWORD(wParam); //
hClickMenu = (HMENU)lParam;
if (HIWORD(wParam) & MF_POPUP) {
if (hClickMenu == hMenu)
submenuID = itemID;
else
itemID += 100 * (submenuID + 1);
}
else if (!itemID)
itemID = -1;
SendMessage(hwndStatusBar, SB_SIMPLE, TRUE, 0);
LoadString(GetModuleHandle(NULL), itemID, text, 200);
SendMessage(hwndStatusBar, SB_SETTEXT, 255, (LPARAM)text);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
/* IDM_OPEN, IDM_CLOSE, , IDM_RESIZE
8.1 */
case IDM_ABOUT:
MessageBox(hWnd,
"StatusBar\nVersion 1.0\nCopyright: "
"Finesoft Corporation, 2005.",
"About StatusBar", MB_OK);
break;
default:
break;
}
UpdateToolBar(shapeData);
SendMessage(hwndStatusBar, SB_SIMPLE, FALSE, 0);
UpdateStatusBar(hWnd, shapeData);
InvalidateRect(hWnd, NULL, TRUE);
421
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
brightness = intensity[shapeData.id_bright - ID_DARK];
if (bShow) {
hBrush = CreateSolidBrush(RGB(
shapeData.fRed? brightness : 0,
shapeData.fGreen? brightness : 0,
shapeData.fBlue? brightness : 0));
hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
//
// -
//
GetClientRect(hWnd, &rect);
GetWindowRect(hwndToolBar, &rcTB);
tbHeight = rcTB.bottom - rcTB.top;
GetWindowRect(hwndStatusBar, &rcSB);
sbHeight = rcSB.bottom - rcSB.top;
x0 = rect.right / 2;
y0 = tbHeight + (rect.bottom - tbHeight - sbHeight) / 2;
//
if (shapeSize == MIN) {
x1 = x0 - W/2; y1 = y0 - H/2;
x2 = x0 + W/2; y2 = y0 + H/2;
}
else {
x1 = 0; y1 = tbHeight;
x2 = rect.right; y2 = rect.bottom - sbHeight;
}
//
pt[0].x = (x1
pt[1].x = x2;
pt[2].x = (x1
pt[3].x = x1;
+ x2) /
pt[1].y
+ x2) /
pt[3].y
2; pt[0].y = y1;
= (y1 + y2) / 2;
2; pt[2].y = y2;
= (y1 + y2) / 2;
switch (shapeData.id_shape) {
case ID_RECTANGLE:
Rectangle(hDC, x1, y1, x2, y2);
break;
case ID_RHOMB:
Polygon(hDC, pt, 4); break;
case ID_ELLIPSE:
Ellipse(hDC, x1, y1, x2, y2); break;
}
DeleteObject(SelectObject(hDC, hOldBrush));
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
422
8.
8.5 ()
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
.
,
, UpdateStatusBar.
WM_SIZE WM_COMMAND.
, ,
WM_MENUSELECT:
itemID = LOWORD(wParam);
hClickMenu = (HMENU)lParam;
if (HIWORD(wParam) & MF_POPUP) {
if (hClickMenu == hMenu)
submenuID = itemID;
else
itemID += 100 * (submenuID + 1);
}
else if (!itemID)
itemID = -1;
itemID
.
.
,
(SEPARATOR) Windows WM_MENUSELECT,
LOWORD(wParam) .
, else. ,
wParam MF_POPUP.
itemID 1.
1 .
. 8.10 StatusBar.
.
. 8.10. StatusBar.
423
Progress bar, Slider Spin.
, Progress bar
,
.
.
,
.
CreateWindow Create
WindowEx PROGRESS_CLASS
, :
hwndProgressBar = CreateWindow(PROGRESS_CLASS, NULL, WS_CHILD | WS_VISIBLE,
x, y, width, height, hwndParent, NULL, NULL, NULL);
,
COLOR_HIGHLIGHT1.
CreateWindow PBS_VERTICAL,
.
:
. width
height.
, ,
PBS_SMOOTH.
.
.
(range)
. wMin wMax.
(current position)
.
,
.
,
. 8.12 ( . MSDN).
wMin wMax ,
0 65 535.
PBM_SETRANGE, ,
wMin = 0, wMax = 100.
1
, Windows
.
424
8.
wParam
lParam
PBM_SETRANGE
PBM_SETPOS
PBM_DELTAPOS
nNewPos
nInc
MAKELPARAM
(wMin, wMax)
0
0
PBM_SETSTEP
PBM_STEPIT
nStepInc
0
0
0
PBM_SETBARCOLOR
PBM_SETBKCOLOR
(COLORREF)
clrBar
(COLORREF)
clrBk
nInc
nStepInc
,
. PBM_SETPOS,
PBM_DELTAPOS PBM_STEPIT.
nStepInc, ,
PBM_SETSTEP. ,
nStepInc = 10.
, PBM_STEPIT
wMax ,
wMin .
. 8.12
.
ProgressBar, .
.
.
.
, size
DATA_CHUNK .
,
, wMin = 0, wMax = size / DATA_CHUNK, nStepInc = 1,
PBM_STEPIT.
DATA_CHUNK, , wMax
65 535.
ProgressBar.
Link comctl32.lib. ToolTip
KWndEx.h KWndEx.cpp, .
IDR_MENU1 .
LoadFile IDM_LOAD_FILE.
ProgressBar.cpp , 8.6.
8.6. ProgressBar
//////////////////////////////////////////////////////////////////////
// ProgressBar.cpp
#include <windows.h>
#include <commctrl.h>
425
#include <stdio.h>
#include <fstream>
using namespace std;
#include "KWndEx.h"
#include "resource.h"
#define ID_STATUSBAR 201
#define N_PARTS 2
#define DATA_CHUNK 64
#define FILE_NAME "ProgressBar.cpp"
HWND hwndStatusBar;
HWND hwndProgressBar;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWndEx mainWnd("ProgressBar", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 200);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
char text[100];
RECT rect, r1;
int aWidths[N_PARTS];
ifstream file;
static int size;
static int range;
static int nBytesRead;
//
//
//
double percentage;
char buf[DATA_CHUNK];
static int i;
MSG message;
switch (uMsg)
{
case WM_CREATE:
//
hwndStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd,
ID_STATUSBAR);
//
426
8.
8.6 ()
SendMessage(hwndStatusBar, SB_SETMINHEIGHT, 24, 0);
aWidths [0] = 50;
aWidths [1] = -1;
SendMessage(hwndStatusBar, SB_SETPARTS, N_PARTS, (LPARAM)aWidths);
// 1-
SendMessage(hwndStatusBar, SB_GETRECT, 1, (LPARAM)&r1);
//
hwndProgressBar = CreateWindow(PROGRESS_CLASS, NULL,
WS_CHILD | WS_VISIBLE,
r1.left + 3, r1.top + 3, r1.right - r1.left, r1.bottom - r1.top,
hwndStatusBar, NULL, NULL, NULL);
break;
case WM_SIZE:
SendMessage (hwndStatusBar, WM_SIZE, wParam, lParam);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_LOAD_FILE:
//
file.open(FILE_NAME, ios::in | ios::binary);
if (!file) {
MessageBox(hWnd, " ", NULL, MB_OK | MB_ICONSTOP);
break;
}
//
file.seekg(0, ios::end);
size = file.tellg();
file.seekg(0, ios::beg);
//
range = size / DATA_CHUNK;
SendMessage(hwndProgressBar, PBM_SETRANGE, 0,
MAKELPARAM(0, range));
SendMessage(hwndProgressBar, PBM_SETSTEP, 1, 0);
SendMessage(hwndProgressBar, PBM_SETPOS, 0, 0);
InvalidateRect(hWnd, NULL, FALSE);
nBytesRead = 0;
//
while (!file.eof()) {
//
file.read(buf, DATA_CHUNK);
nBytesRead += DATA_CHUNK;
if (file.eof()) break;
//
// ...
//
percentage = 100.0 * nBytesRead / size;
427
:
#define FILE_NAME "ProgressBar.cpp"
,
.
428
8.
,
, :
SendMessage(hwndStatusBar, SB_GETRECT, 1, (LPARAM)&r1);
while.
,
PBM_STEPIT.
Sleep(100),
100 .
. ,
ProgressBar.cpp ,
.
if(PeekMessage(&message, hWnd, 0, 0, PM_REMOVE)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
,
.
1.
. 8.11 ProgressBar
LoadFile.
. 8.11. ProgressBar
, ,
CreateWindow PBS_SMOOTH.
, Slider, Trackbar,
.
,
.
.
Slider CreateWindow
CreateWindowEx TRACKBAR_CLASS
, :
429
WS_CHILD WS_VISIBLE
, (. 8.13).
8.13. Slider
TBS_HORZ
( )
TBS_VERT
TBS_AUTOTICKS
TBS_NOTICKS
- ,
TBS_RIGHT
() ;
.
TBS_LEFT
() ;
TBS_BOTH
TBS_TOOLTIPS
.
Slider
Controls
.
,
, Layout.
Slider Properties General
ID . Styles,
. 8.12, .
Orientation
: Horizontal ( ) Vertical. , Point,
: Both ( ), Top/Left
Bottom/Right. Tick marks , Auto ticks
TBS_AUTOTICKS, Border
.
430
8.
.
Trackbar.
Slider ,
. wMin
wMax. wMin = 0, wMax = 100.
, TBM_SETRANGE.
.
, . ,
.
,
, (line).
. ,
TBM_SETLINESIZE.
,
Page Up Page Down, (page).
.
, TBM_SETPAGESIZE.
Auto ticks (TBS_AUTOTICKS),
wFreq,
. , TBM_SETTICFREQ.
,
WM_HSCROLL WM_VSCROLL
(Horizontal Vertical). wParam
, lParam .
. 8.14. TB_THUMBPOSITION
TB_THUMBTRACK wParam .
8.14. Slider
TB_LINEUP
(VK_LEFT)
(VK_UP)
TB_LINEDOWN
(VK_RIGHT) (VK_DOWN)
TB_PAGEUP
Page Up (VK_PRIOR)
( , )
TB_ PAGEDOWN
431
TB_THUMBPOSITION
(
TB_THUMBTRACK)
TB_THUMBTRACK
TB_TOP
TB_BOTTOM
,
TBM_GETPOS (. )
,
.
,
TBM_. . 8.15
.
8.15. Slider
wParam
lParam
TBM_GETPOS
TBM_SETPOS
fRedraw
newPos
.
fRedraw TRUE,
TBM_SETRANGE
fRedraw
MAKELPARAM
(wMin, wMax)
TBM_SETTICFREQ
wFreq
TBM_SETLINESIZE
nLineSize
TBM_SETPAGESIZE
nPageSize
TrackBar
TrackBar,
ModelessDlg, 7.
ModelessDlg
.
Slider.
TrackBar.
ModelessDlg (. 7.6) TrackBar ModelessDlg.cpp,
ModelessDlg.rc resource.h,
ModelessDlg TrackBar. ToolTip (
8.4) KWndEx.cpp KWndEx.h.
. Link
comctl32.lib.
ResourceView Workspace.
Dialog
432
8.
IDD_MODELESS. .
Slider, . 8.13.
. 8.13.
ID
Caption
Static text
IDC_STATIC_RED
Red
Static text
IDC_STATIC_GREEN
Green
Static text
IDC_STATIC_BLUE
Blue
Slider
IDC_SLIDER_RED
C Bottom/Right.
Tick marks, Auto ticks, Border
Slider
IDC_SLIDER_GREEN
Slider
IDC_SLIDER_BLUE
TrackBar.cpp,
8.7.
8.7. TrackBar
//////////////////////////////////////////////////////////////////////
// TrackBar.cpp
#include <windows.h>
#include <stdio.h>
#include <commctrl.h>
#include "KWndEx.h"
#include "resource.h"
enum UserMsg { UM_CHANGE = WM_USER+1 };
HWND hModelessDlg;
RECT rcWork; //
int rgb[3]; // R-, G-, B-
BOOL CALLBACK ModelessDlgProc(HWND, UINT, WPARAM, LPARAM);
void AdjustDlgPlace(HWND, HWND);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
433
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWndEx mainWnd("TrackBar", hInstance, nCmdShow, WndProc,
NULL, 100, 100, 400, 270);
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(hModelessDlg, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* , 7.6 */
}
//====================================================================
BOOL CALLBACK ModelessDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hSliderRed;
static HWND hSliderGreen;
static HWND hSliderBlue;
static HWND hStaticRed;
static HWND hStaticGreen;
static HWND hStaticBlue;
char text[100];
switch (uMsg) {
case WM_INITDIALOG:
// Slider
hSliderRed = GetDlgItem(hDlg, IDC_SLIDER_RED);
hSliderGreen = GetDlgItem(hDlg, IDC_SLIDER_GREEN);
hSliderBlue = GetDlgItem(hDlg, IDC_SLIDER_BLUE);
hStaticRed = GetDlgItem(hDlg, IDC_STATIC_RED);
hStaticGreen = GetDlgItem(hDlg, IDC_STATIC_GREEN);
hStaticBlue = GetDlgItem(hDlg, IDC_STATIC_BLUE);
// Slider
SendMessage(hSliderRed, TBM_SETRANGE, TRUE, MAKELONG(0, 255));
SendMessage(hSliderRed, TBM_SETTICFREQ, 32, 0);
SendMessage(hSliderGreen, TBM_SETRANGE, TRUE, MAKELONG(0, 255));
SendMessage(hSliderGreen, TBM_SETTICFREQ, 32, 0);
SendMessage(hSliderBlue, TBM_SETRANGE, TRUE, MAKELONG(0, 255));
SendMessage(hSliderBlue, TBM_SETTICFREQ, 32, 0);
//
SendMessage(hDlg, WM_HSCROLL, 0, 0);
434
8.
8.7 ()
return TRUE;
case WM_HSCROLL:
// Slider
rgb[0] = SendMessage(hSliderRed, TBM_GETPOS, 0, 0);
sprintf(text, "Red = %d", rgb[0]);
SetWindowText(hStaticRed, text);
rgb[1] = SendMessage(hSliderGreen, TBM_GETPOS, 0, 0);
sprintf(text, "Green = %d", rgb[1]);
SetWindowText(hStaticGreen, text);
rgb[2] = SendMessage(hSliderBlue, TBM_GETPOS, 0, 0);
sprintf(text, "Blue = %d", rgb[2]);
SetWindowText(hStaticBlue, text);
//
SendMessage(GetParent(hDlg), UM_CHANGE, 0, 0);
break;
}
return FALSE;
}
//====================================================================
void AdjustDlgPlace(HWND hParent, HWND hDlg) {
/* , 7.6 */
}
//////////////////////////////////////////////////////////////////////
WM_INITDIALOG
TBM_SETRANGE
TBM_SETTICFREQ.
WM_HSCROLL
, TBM_GETPOS.
rgb[0], rgb[1] rgb[2]
hStaticRed, hStaticGreen hStaticBlue,
.
WndProc, UM_CHANGE.
:
SendMessage(GetParent(hDlg), UM_CHANGE, 0, 0);
. 8.14. TrackBar
435
UM_CHANGE,
WndProc, , ,
7.6.
. 8.14 .
.
(Spin) ,
. , ,
.
,
(buddy window).
.
.
.
(. 8.15).
. 8.15.
,
. , Tab control
(. 8.16).
.
CreateWindowEx UPDOWN_CLASS.
CreateUpDownControl,
,
, .
. Spin
Controls
.
Spin Properties General ID
. Styles,
. 8.17, .
436
8.
Orientation .
Vertical,
Horizontal.
Alignment
:
Alignment
Unattached
(,
)
Left
(
)
Right
(
)
Styles :
Auto buddy
,
,
Wrap
,
( ) (
) . , .
,
Arrow keys
( )
,
. , Spin
. , Auto buddy Set buddy integer.
Arrow keys ,
.
437
.
,
. ,
.
.
Spin
WM_VSCROLL WM_HSCROLL (
), wParam
SB_THUMBPOSITION. ,
UDN_DELTAPOS WM_NOTIFY.
.
,
WM_VSCROLL WM_HSCROLL. , Spin
UDM_GETPOS.
Edit Box WM_COMMAND
EN_CHANGE. ,
(
), .
Spinner.
,
UDM_. . 8.16
, .
8.16. Spin
wParam
lParam
UDM_GETPOS
UDM_SETPOS
0
0
0
MAKELPARAM (nPos, 0)
UDM_SETBASE
nBase
UDM_SETRANGE
MAKELPARAM
(nUpper, nLower)
.
nBase 10 16.
( 0x7FFF...0x7FFF)
UDM_SETRANGE,
nLower=100 nUpper=0.
, .
, ,
, MSDN .
438
8.
, . 8.16, 16
Spin.
Comctl32.dll, 4.71, 32
, ,
. 8.17.
8.17. 32- Spin
wParam
lParam
UDM_GETPOS32
(LPBOOL)
pfError
.
pfError ,
FALSE,
, TRUE
UDM_SETPOS32
nPos
UDM_SETRANGE32
iLow
iHigh
0x7FFFFFFF 0x7FFFFFF
Spinner
Spinner,
TrackBar, .
TrackBar .
.
Spinner.
TrackBar (. 8.7) Spinner
.cpp, .h .rc,
TrackBar Spinner.
. Link
comctl32.lib.
ResourceView Workspace.
Dialog
IDD_MODELESS.
Slider .
. 8.18.
( Edit Box
Spin), . 8.18.
.
:
ID
Edit Box
Edit Box
IDC_EDIT_RED
IDC_EDIT_GREEN
Edit Box
IDC_EDIT_BLUE
Spin
IDC_SPIN_RED
Spin
IDC_SPIN_GREEN
Spin
IDC_SPIN_BLUE
Spinner.cpp , 8.8.
439
8.8. Spinner
//////////////////////////////////////////////////////////////////////
// Spinner.cpp
#include <windows.h>
#include <stdio.h>
#include <commctrl.h>
#include "KWndEx.h"
#include "resource.h"
enum UserMsg { UM_CHANGE = WM_USER+1 };
HWND hModelessDlg;
RECT rcWork; //
int rgb[3]; // R-, G-, B-
BOOL CALLBACK ModelessDlgProc(HWND, UINT, WPARAM, LPARAM);
void AdjustDlgPlace(HWND, HWND);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWndEx mainWnd("Spinner", hInstance, nCmdShow, WndProc,
NULL, 100, 100, 400, 260);
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(hModelessDlg, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* , 7.6 */
}
//====================================================================
BOOL CALLBACK ModelessDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hSpinRed;
static HWND hSpinGreen;
static HWND hSpinBlue;
static HWND hStaticRed;
static HWND hStaticGreen;
static HWND hStaticBlue;
switch (uMsg) {
case WM_INITDIALOG:
// Spin
hSpinRed = GetDlgItem(hDlg, IDC_SPIN_RED);
hSpinGreen = GetDlgItem(hDlg, IDC_SPIN_GREEN);
hSpinBlue = GetDlgItem(hDlg, IDC_SPIN_BLUE);
440
8.
8.8 ()
hStaticRed = GetDlgItem(hDlg, IDC_STATIC_RED);
hStaticGreen = GetDlgItem(hDlg, IDC_STATIC_GREEN);
hStaticBlue = GetDlgItem(hDlg, IDC_STATIC_BLUE);
// Spin
SendMessage(hSpinRed, UDM_SETRANGE, TRUE, MAKELPARAM(255, 0));
SendMessage(hSpinGreen, UDM_SETRANGE, TRUE, MAKELPARAM(255, 0));
SendMessage(hSpinBlue, UDM_SETRANGE, TRUE, MAKELPARAM(255, 0));
return TRUE;
case WM_VSCROLL:
// Spin
rgb[0] = SendMessage(hSpinRed, UDM_GETPOS, 0, 0);
rgb[1] = SendMessage(hSpinGreen, UDM_GETPOS, 0, 0);
rgb[2] = SendMessage(hSpinBlue, UDM_GETPOS, 0, 0);
//
SendMessage(GetParent(hDlg), UM_CHANGE, 0, 0);
break;
case WM_COMMAND:
//
//
if (HIWORD(wParam) == EN_CHANGE)
SendMessage(hDlg, WM_VSCROLL, 0, 0);
break;
}
return FALSE;
}
//====================================================================
void AdjustDlgPlace(HWND hParent, HWND hDlg) {
/* , 7.6 */
}
//////////////////////////////////////////////////////////////////////
, , .
WM_COMMAND EN_CHANGE.
WM_VSCROLL,
.
. 8.19 .
. 8.19. Spinner.
441
Win32 API.
[5]
MSDN.
"
: Kernel ( ) User ( ). "
, , .
, ,
, , .
Windows NT/2000 "
: (privileged kernel mode part)
(nonprivileged user
mode part).
:
HAL (Hardware Abstraction Layer) , "
, .
(MicroKernel), , "
, , "
.
,
, ".
"
.
, "
, , "
.
"
, , , , "
, .
442
9.
,
. , "
. (, "
) , "
.
, . "
Windows.
, (, CreateFile),
. "
.
, "
. "
. ,
.
.
, . , "
" , , "
. ,
,
, .
, , "
. "
. "
, .
" ,
. ,
.
:
(signaled state) (nonsignaled state).
, Micro"
soft . "
wait .
(security
descriptor). , "
.
. , "
.
, , "
SECURITY_ATTRIBUTES.
NULL, "
. "
,
.
, ,
CloseHandle:
BOOL CloseHandle(HANDLE hObject);
, "
, hObject. ,
443
hObject
. ,
.
, CloseHandle FALSE,
GetLastError ERROR_INVALID_HANDLE.
CloseHandle "
. hObject "
, .
, .
, .
, CloseHandle,
.
, "
, . "
, ,
:
,
, ;
"
, ;
, , "
,
.
Win32 API , "
: ) "
; ) ; ) "
.
.
, "
.
Windows .
(process) , "
. ,
, , . "
. "
, (primary thread).
, , ,
. , ,
, . .
(thread) , "
.
. (thread context) , "
444
9.
. , "
, , .
, "
.
,
.
, "
.
. , "
.
,
. 9.1.
. 9.1.
"
.
, .
C .
" "
, . Windows
.
,
, .
.
,
. Windows "
, . ,
6 Windows 2000 Professional 36 Windows 2000 Server.
, ,
3,
, .
Windows 2000 Professional
, Windows 2000 Server 12 "
.
( ) 10
15 , .
445
Windows 32 ( 0 31) ,
. :
, ,
.
. 9.1.
9.1.
CreateProcess
Idle
IDLE_PRIORITY_CLASS
Below normal
BELOE_NORMAL_PRIORITY_CLASS
Normal
NORMAL_PRIORITY_CLASS
Above normal
ABOVE_NORMAL_PRIORITY_CLASS
10
High
HIGH_PRIORITY_CLASS
13
Realtime
REALTIME_PRIORITY_CLASS
24
446
9.
, , Normal. "
. , "
, , , "
, . Normal
(foreground) (background). ,
, "
, . "
.
, High, "
. High
, . "
High ,
" , , winlogon.exe.
"
, High
, , "
Normal. "
SetPrioriryClass.
Realtime,
,
, .
. , "
,
, Realtime
.
. "
,
SetThreadPriority. . 9.2 .
9.2.
SetThreadPriority
Idle
THREAD_PRIORIRY_IDLE
Realtime 16, 1
Lowest
THREAD_PRIORIRY_LOWEST
Below normal
THREAD_PRIORIRY_BELOW_NORMAL
Normal
THREAD_PRIORIRY_NORMAL
Above normal
THREAD_PRIORIRY_ABOVE_NORMAL
Highest
THREAD_PRIORIRY_HIGHEST
Time critical
THREAD_PRIORIRY_TIME_CRITICAL
Realtime 31, 15
447
"
(Explorer), (Start),
. , Win32 API "
, .
CreateProcess
CreateProcess .
:
BOOL CreateProcess(
LPCTSTR lpApplicationName, //
LPTSTR lpCommandLine,
//
LPSECURITY_ATTRIBUTES processAttributes, //
LPSECURITY_ATTRIBUTES threadAttributes, //
BOOL bInheritHandles, //
DWORD dwCreationFlags, //
LPVOID lpEnvironment, //
LPCTSTR lpCurrentDirectory, //
LPSTARTUPINFO lpStartupInfo, // STARTUPINFO
LPPROCESS_INFORMATION lpProcessInformation //
// PROCESS_INFORMATION
);
.
lpCommandLine , "
CreateProcess . ,
, "
. , .exe.
:
1. .
2. Windows.
3. Windows.
4. , PATH.
, ,
.
lpApplicationName NULL, "
lpCommandLine.
CreateProcess
STARTUPINFO PROCESS_INFORMATION:
STARTUPINFO si;
PROCESS_INFORMATION pi;
CreateProcess.
STARTUPINFO "
. , "
.
STARTUPINFO , cb
.
448
9.
, CreateProcess
TRUE PROCESS_
INFORMATION, :
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
//
HANDLE hThread;
//
DWORD dwProcessId; //
DWORD dwThreadId; //
} PROCESS_INFORMATION;
CreateProcess "
MSDN.
.
CreateProcess,
, "
.
1 ,
DLL, .
, , "
.
C/C++, WinMain, wWinMain, main
wmain2 .
:
, WinMain, "
( ).
ExitProcess.
TerminateProcess (
).
. .
,
. "
, , "
. C++, "
, .
, , "
, .
, ExitProcess. "
MSDN .
. [5], ,
.
.
w Unicode" .
main wmain .
449
C++ . "
, , "
. .
TerminateProcess .
ExitProcess , "
. TerminateProcess
, .
, ,
"
. , "
.
.
, ExitThread
, TerminateThread. "
, , "
. "
.
.
.
User" GDI", , ,
, .
, (signaled), "
.
(detached processes). ,
,
. Explorer.
, .
CreateMyProcess , "
Windows (calc.exe).
CreateMyProcess, "
IDR_MENU1. Create
process IDM_CREATE_PROCESS. "
CreateMyProcess KWnd.h KWnd.cpp 1.2
.
9.1. CreateMyProcess
//////////////////////////////////////////////////////////////////////
// CreateMyProcess.cpp
#include <windows.h>
#include "resource.h"
#include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
450
9.
451
CreateMyProcess "
, Create process. "
. "
,
.
. "
: WinMain, wWinMain, main wmain.
, ,
:
DWORD WINAPI ThreadFunc(PVOID pvParam) {
DWORD dwResult = 0;
. . .
return dwResult;
}
. "
. , ,
, ,
. ,
.
, "
: WinMain, wWinMain, main wmain,
.
CreateThread
CreateThread:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES threadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
//
//
//
//
//
//
CreateProcess, "
(0 NULL).
, .
( 9.2).
CreateThread
, . "
.
, .
:
( );
452
9.
ExitThread ( ,
ExitProcess);
Terminate
Thread ( );
, ( ).
User", "
, (hooks).
,
.
Sleep
"
, Sleep:
VOID Sleep(DWORD dwMilliseconds);
dwMilliseconds "
. "
.
Sleep, "
.
,
. , "
, 10.
dwMilliseconds , "
, "
. "
, .
10 ( ) "
Sleep.
CreateMyThreads "
.
9.2. CreateMyThreads
//////////////////////////////////////////////////////////////////////
// CreateMyThreads.cpp
#include <windows.h>
#include <string>
using namespace std;
#include "KWnd.h"
enum UserMsg { UM_THREAD_DONE = WM_USER+1 };
struct ThreadManager {
ThreadManager(string _name) : name(_name) { nValue = 0; }
HWND hwndParent;
9.2 ()
string name;
int nValue;
};
ThreadManager tm_A(string(" A"));
ThreadManager tm_B(string(" B"));
ThreadManager tm_C(string(" C"));
DWORD WINAPI ThreadFuncA(LPVOID);
DWORD WINAPI ThreadFuncB(LPVOID);
DWORD WINAPI ThreadFuncC(LPVOID);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("CreateMyThreads", hInstance, nCmdShow, WndProc,
NULL, 100, 100, 400, 160);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static HANDLE hThreadA, hThreadB, hThreadC;
static char text[100];
ThreadManager* pTm;
static int y = 0;
switch (uMsg)
{
case WM_CREATE:
tm_A.hwndParent = hWnd;
hThreadA = CreateThread(NULL, 0, ThreadFuncA, &tm_A, 0, NULL);
if (!hThreadA)
MessageBox(hWnd, "Error of create hThreadA", NULL, MB_OK);
tm_B.hwndParent = hWnd;
hThreadB = CreateThread(NULL, 0, ThreadFuncB, &tm_B, 0, NULL);
if (!hThreadB)
MessageBox(hWnd, "Error of create hThreadB", NULL, MB_OK);
tm_C.hwndParent = hWnd;
hThreadC = CreateThread(NULL, 0, ThreadFuncC, &tm_C, 0, NULL);
453
454
9.
if (!hThreadC)
MessageBox(hWnd, "Error of create hThreadC", NULL, MB_OK);
break;
case UM_THREAD_DONE:
pTm = (ThreadManager*)wParam;
sprintf(text, "%s: count = %d", pTm->name.c_str(), pTm->nValue);
y += 30;
InvalidateRect(hWnd, NULL, FALSE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
TextOut(hDC, 20, y, text, strlen(text));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
CloseHandle(hThreadA);
CloseHandle(hThreadB);
CloseHandle(hThreadC);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
DWORD WINAPI ThreadFuncA(LPVOID lpv)
{
ThreadManager* pTm = (ThreadManager*)lpv;
int count = 0;
for (int i = 0; i < 100000000; ++i) count++;
pTm->nValue = count;
SendMessage(pTm->hwndParent, UM_THREAD_DONE, (WPARAM)pTm, 0);
return 0;
}
//====================================================================
DWORD WINAPI ThreadFuncB(LPVOID lpv)
{
ThreadManager* pTm = (ThreadManager*)lpv;
int count = 0;
for (int i = 0; i < 50000000; ++i) count++;
pTm->nValue = count;
455
9.2 ()
SendMessage(pTm->hwndParent, UM_THREAD_DONE, (WPARAM)pTm, 0);
return 0;
}
//====================================================================
DWORD WINAPI ThreadFuncC(LPVOID lpv)
{
ThreadManager* pTm = (ThreadManager*)lpv;
int count = 0;
for (int i = 0; i < 20000; ++i) count++;
pTm->nValue = count;
SendMessage(pTm->hwndParent, UM_THREAD_DONE, (WPARAM)pTm, 0);
return 0;
}
//////////////////////////////////////////////////////////////////////
. 9.2. CreateMyThreads
( : A,
B, C), C, B "
A.
.
CreateThread. . "
, C/C++
CreateThread.
456
9.
A
:
hThreadA = (HANDLE)_beginthreadex(NULL, 0, (PTHREAD_START)ThreadFuncA,
(void*)&tm_A, 0, NULL);
_beginthreadex "
C/C++,
. ProjectSettings "
Project Settings C/C++.
Category Code Generation, Use run-time library
, Debug Multithreaded.
,
, , "
.
, "
. , "
9.3.
9.3. BadCount
//////////////////////////////////////////////////////////////////////
// BadCount.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#define N 50000000
long g_counter = 0;
DWORD WINAPI ThreadFunc(LPVOID);
void IncCounter();
void DecCounter();
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("BadCount", hInstance, nCmdShow, WndProc,
NULL, 100, 100, 400, 100);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
9.3 ()
DispatchMessage(&msg);
}
return (msg.wParam);
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
HANDLE hThread;
char text[100];
switch (uMsg)
{
case WM_CREATE:
hThread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
if (!hThread)
MessageBox(hWnd, "Error of CreateThread", NULL, MB_OK);
DecCounter();
WaitForSingleObject(hThread, INFINITE);
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
sprintf(text, "g_counter = %d", g_counter);
TextOut(hDC, 20, 20, text, strlen(text));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
DWORD WINAPI ThreadFunc(LPVOID lpv)
{
IncCounter();
return 0;
}
//====================================================================
void IncCounter()
{
for (int i = 0; i < N; ++i) ++g_counter;
}
//====================================================================
void DecCounter()
{
for (int i = 0; i < N; ++i) --g_counter;
}
//////////////////////////////////////////////////////////////////////
457
458
9.
CreateThread ,
ThreadFunc. ThreadFunc
IncCounter, N "
g_counter.
, "
DecCounter. DecCounter
N g_counter.
DecCounter "
WaitForSingleObject.
WaitForSingleObject(hThread, INFINITE);
(INFINITE),
hThread.
, InvalidateRect,
Windows WM_PAINT. , "
WndProc g_counter .
, "
g_counter = 0.
N . 50 000 000
. "
, Intel Celeron
Intel Pentium. , 2 IncCounter
, DecCounter, 150 .
, .
, HyperThreating,
g_counter.
HyperThreating , .
?
, "
! .
, DecCounter "
. , , "
g_counter . ,
100 000. ,
99 999 .
, "
, . , "
IncCounter 50 000 ,
g_counter 150 000.
, "
.
. , "
99 999 g_counter.
"
!
, ,
"
.
459
, ,
. "
:
( );
" .
, "
. Win"
dows 2000 :
API";
.
.
Interlocked-
(atomic
access) . Win32
API
. Interlocked" ,
(DWORD).
InterlockedIncrement,
LONG InterlockedIncrement(LPLONG lpAddend);
32" ,
lpAddend. .
InterlockedDecrement InterlockedIncrement, 32" .
LONG InterlockedExchange(LPLONG lpTarget, LONG Value);
PVOID InterlockedExchangePointer(PVOID* ppvTarget, PVOID pvValue);
LONG, "
, , .
32" 32" "
. 64" 32" "
, 64".
.
, "
, , :
LONG InterlockedExchangeAdd(LPLONG lpAddend, LONG Increment);
460
9.
"
:
LONG InterlockedCompareExchange(LPLONG lpDestination, LONG Exchange,
LONG Comparand);
PVOID InterlockedCompareExchangePointer(PVOID* ppvDestination,
PVOID pvExchange, PVOID pvComparand);
, , "
, , "
, . 32"
32" . 64" "
32" , 64".
, "
.
BadCount (. 9.3),
"
g_counter . "
, . "
IncCounter
++g_counter;
:
InterlockedIncrement(&g_counter);
, DecCounter
--g_counter;
:
InterlockedDecrement(&g_counter);
, BadCount "
. ,
", GoodCount!
(critical section) , "
. "
, "
,
, .
CRITICAL_SECTION:
CRITICAL_SECTION cs;
"
, . "
"
InitializeCriticalSection:
InitializeCriticalSection(&cs);
,
EnterCriticalSection:
EnterCriticalSection(&cs);
461
,
, "
. ,
, .
EnterCriticalSection , "
.
LeaveCriticalSection:
LeaveCriticalSection(&cs);
, "
. ,
.
.
, "
DeleteCriticalSection.
Windows NT/2000
TryEnterCriticalSection, ,
:
BOOL bAcquired
if (bAcquired)
//
. . .
}
else {
//
. . .
= TryEnterCriticalSection(&cs);
{
,
. ,
, EnterCriticalSection, "
, else.
Interlocked", "
.
.
.
, .
. wait".
Wait-
(signaled state),
(nonsignaled state). :
;
462
9.
.
Wait"
" . "
, , "
".
WaitForSingleObject
:
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMillisecond);
, hHandle
, . dwMillisecond "
" (time out) , "
, .
dwMillisecond ,
. INFINITE "
dwMillisecond ".
:
WAIT_OBJECT_0
WAIT_TIMEOUT
-,
WAIT_FAILED
.
GetLastError
WaitForSingleObject:
DWORD dw = WaitForSingleObject(hProcess, 5000);
switch (dw) {
case WAIT_OBJECT_0:
//
break;
case WAIT_TIMEOUT:
// , 5000
break;
case WAIT_FAILED:
// .
break;
}
, INFINITE
WaitForSingleObject. hHandle "
, . "
, .
463
WaitForMultipleObjects
:
DWORD WaitForMultipleObjects(DWORD nCount, CONST HANDLE* lpHandles,
BOOL fWaitAll, DWORD dwMilliseconds);
, WaitForSingleObject,
"
.
nCount .
1 MAXIMUM_WAIT_OBJECTS.
Windows 64. lpHandles
.
.
WaitForMultipleObjects "
, . fWaitAll
. TRUE "
, FALSE .
, .
, "
. WAIT_TIMEOUT WAIT_FAILED "
WaitForSingleObject. fWaitAll TRUE
,
WAIT_OBJECT_0. fWaitAll FALSE, "
, .
WAIT_OBJECT_0 WAIT_OBJECT_0 + nCount 1. "
, WAIT_OBJECT_0, "
lpHandles.
WaitForMultipleObjects:
HANDLE hp[3];
hp[0] = hProcess0;
hp[1] = hProcess1;
hp[2] = hProcess2;
DWORD dw = WaitForMultipleObjects (3, hp, FALSE, 4000);
switch (dw) {
case WAIT_OBJECT_0 + 0:
// hp[0]
break;
case WAIT_OBJECT_0 + 1:
// hp[1]
break;
case WAIT_OBJECT_0 + 2:
// hp[2]
break;
case WAIT_TIMEOUT:
// 4000
break;
case WAIT_FAILED:
// .
break;
}
464
9.
WaitForSingleObject WaitForMultipleObjects
. "
, "
. WAIT_OBJECT_0 , "
WAIT_OBJECT_0. ,
WAIT_TIMEOUT WAIT_FAILED.
" .
, , WaitForSingleObject "
(" "
). , "
WAIT_OBJECT_0.
" . "
.
, "
, Microsoft .
, .
.
(event) .
.
", .
" . "
: (manualreset events)
(autoreset events).
, .
CreateEvent,
:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES eventAttributes, //
BOOL bManualReset,
//
BOOL bInitialState,
//
LPCTSTR pszName
//
);
. "
, .
, . , B
465
" EventName.
A . "
, A
hEvent. A "
", "
.
, , B
, , .
CreateEvent NULL, "
GetLastError, , 6 (ERROR_INVALID_HANDLE).
, (EventName)
CreateEvent .
EventName.
,
.
" . , "
A hEvent EventName.
:
CreateEvent pszName "
( );
DuplicateHandle;
OpenEvent pszName .
OpenEvent :
HANDLE OpenEvent(
DWORD dwDesiredAccess, //
BOOL bInheritHandle,
//
LPCTSTR pszName
//
);
dwDesiredAccess ".
:
EVENT_ALL_ACCESS
EVENT_MODIFY_STATE
SetEvent
ResetEvent
SYNCHRONIZE
wait-
OpenEvent , ,
pszName CreateEvent, "
, dwDesiredAccess.
bInheritHandle , "
. pszName
".
, "
". ,
NULL. GetLastError "
.
466
9.
,
BOOL SetEvent(HANDLE hEvent);
hEvent , "
.
.
, "
. "
,
ResetEvent.
" 9.4 9.5.
(semaphore) .
32" "
. , "
, .
CreateSemaphore:
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES semaphoreAttributes, //
LONG lInitialCount, //
LONG lMaximumCount, //
LPCTSTR pszName
//
);
, :
HANDLE hSem = CreateSemaphore(NULL, 0, 5, "MySemaphore");
" ,
, .
"
lReleaseCount, ReleaseSemaphore:
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
//
LONG lReleaseCount,
//
LPLONG lpPreviousCount //
);
, , "
. ,
lpPreviousCount NULL.
, () "
, OpenSemaphore:
HANDLE OpenSemaphore (
DWORD dwDesiredAccess, //
BOOL bInheritHandle,
//
LPCTSTR pszName
//
);
467
dwDesiredAccess "
. :
SEMAPHORE_ALL_ACCESS
SEMAPHORE _MODIFY_STATE
ReleaseSemaphore
SYNCHRONIZE
wait
, "
". , "
NULL. GetLastError "
.
, wait"
, . Wait"
.
( ), , "
. , "
. , wait"
,
.
wait" ,
( ), "
. ,
. , "
, .
(mutex)
. "
,
". .
, "
.
.
" "
CreateMutex:
HANDLE CreateMutex (
LPSECURITY_ATTRIBUTES mutexAttributes, //
BOOL bInitialOwner,
// -
LPCTSTR pszName
//
);
bInitialOwner . "
FALSE, "
. "
" . "
TRUE, " "
468
9.
, "
. " , "
.
, () "
, OpenMutex:
HANDLE OpenMutex(DWORD dwDesiredAccess, BOOL bInheritHandle,
LPCTSTR pszName);
dwDesiredAccess :
MUTEX_ALL_ACCESS
SYNCHRONIZE
wait-,
ReleaseMutex
, "
". "
NULL.
wait"
, . Wait""
". "
,
. wait" "
"
, .
wait" , " "
, . "
, " (
),
, . "
. "
" .
, ,
, , ReleaseMutex.
ReleaseMutex .
,
".
"
. , , , "
wait" .
.
ReleaseMutex
.
, , , , "
? , ,
.
, "
. wait" WAIT_ABANDONED
WAIT_OBJECT_0. , .
469
wait" "
WAIT_ABANDONED, "
. "
.
"
.
. (Interprocess
Communication, IPC) "
. "
(World Wide Web).
IPC, Windows:
(clipboard)
IPC.
.
. DLL "
, (shared). DLL,
,
.
WM_COPYDATA,
.
(shared memory)
. "
.
ActiveX , "
. Microsoft
IDataObject.
Distibuted Component Object Model (DCOM),
ActiveX RPC.
(pipes) . "
, , "
470
9.
. (anonymous
pipes) (named pipes). "
. , "
WinNT/2000,
.
.
(sockets) ,
.
. , "
, "
. Windows API "
.
.
. Win32 4 ,
. , 32"
0x00000000 0xFFFFFFFF. , "
4 294 967 296 ,
.
, 0x80000000
0xFFFFFFFF, ,
.
. , "
.
471
RAM ,
, 4 , "
.
(page file), RAM
, .
(swap file).
. "
,
4 . Windows "
.
, ,
. "
:
, , .
, "
.
, " "
. ,
Page Fault ( ). "
. ,
. "
, .
.
, "
, ,
.
"
, .
Invalid Page Fault, "
.
(API)
(Virtual Memory Manager VMM) "
.
, (page swapping).
,
(API) :
Virtual Memory API ,
. , VirtualAlloc
VirtualFree
.
472
9.
,
. "
, ,
. .
:
1. , ,
( CreateFile).
2. CreateFileMapping.
, CreateFile.
3. "
( MapViewOfFile).
,
:
1. "
( UnmapViewOfFile).
2. .
3. .
:
HANDLE hFile, hFileMapping;
PVOID pArray;
hFile = CreateFile("File Name", ... );
hFileMapping = CreateFileMapping(hFile, ... );
CloseHandle(hFile) ;
pArray = MapViewOfFile(hFileMapping, ... );
CloseHandle(hFileMapping) ;
//
/* , pArray */
//
UnmapViewOfFile(pArray);
"
. "
.
.
. , "
,
.
473
.
,
. ,
, "
.
.
"
, . "
. ,
Win32 API "
,
.
, .
", CreateFile. "
CreateFileMapping INVALID_HANDLE_VALUE (
1) hFile. CreateFileMapping
C", .
, , "
OpenFileMapping .
,
,
. " "
.
, "
CloseHandle. ,
, .
-
(, )
WM_COPYDATA, ,
.
, .
, .
, "
, , "
.
. " "
.
, " "
. , "
, . "
.
"
ClientApp ServerApp. 9.3 ,
.
474
9.
. 9.3.
,
.
.
,
""
. , "
"
.
. "
. , "
, . 9.3 36.
WM_COPYDATA
WM_COPYDATA , ,
.
SendMessage, "
, .
FindWindow, :
hwndServer = FindWindow(NULL, "ServerApp");
"
, ServerApp.
WM_COPYDATA, "
COPYDATASTRUCT.
:
typedef struct tagCOPYDATASTRUCT {
ULONG_PTR dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
475
lpData , "
. lpData NULL, cbData
, lpData.
"
(dwData lpData) .
WM_COPYDATA SendMessage,
COPYDATASTRUCT lParam.
, "
" request , "
ServerApp:
COPYDATASTRUCT cds;
char request[80];
sprintf(request, "ClientApp");
cds.lpData = &request;
cds.cbData = strlen(request);
hwndServer = FindWindow(NULL, "ServerApp");
SendMessage(hwndServer, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds);
, WM_COPYDATA,
, lpData, . lpData
WM_COPYDATA.
"
, .
, lpData, "
, "
.
, , .
ServerApp
ServerApp 9.4.
9.4. ServerApp
//////////////////////////////////////////////////////////////////////
// ServerApp.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#define MAX_STR_SIZE 80
#define MAX_N 10 //
int N = 0;
//
HANDLE hEvtRecToServ[MAX_N]; // " "
char eventName[MAX_N][MAX_STR_SIZE + 8]; //
HANDLE
HANDLE
HANDLE
HANDLE
hEvtServIsExist;
hEvtServIsFree;
hEvtServIsDone;
hFileMap = NULL;
struct ThreadManager {
HWND hwndParent;
};
//
//
//
//
" "
" "
" "
" "
476
9.
ThreadManager tm; //
DWORD WINAPI ThreadFunc(LPVOID);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("ServerApp", hInstance, nCmdShow, WndProc,
NULL, 100, 100, 450, 100);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
COPYDATASTRUCT* pCds;
COPYDATASTRUCT cds;
static char request[MAX_STR_SIZE];
char suffix[8];
HWND hwndClient;
static HANDLE hThread;
HWND* pHwnd = &hWnd;
int i;
switch (uMsg)
{
case WM_CREATE:
hEvtServIsExist = OpenEvent(EVENT_ALL_ACCESS, FALSE, "Server");
if (hEvtServIsExist) {
MessageBox(hWnd, " . 2 .",
"ServerApp", MB_OK | MB_ICONSTOP | MB_SYSTEMMODAL);
PostQuitMessage(0);
}
else
hEvtServIsExist = CreateEvent(NULL, FALSE, FALSE, "Server");
break;
case WM_COPYDATA: //
if (N == MAX_N) {
MessageBox(hWnd, " . ",
"ServerApp", MB_OK | MB_ICONSTOP | MB_SYSTEMMODAL);
break;
}
//
pCds = (COPYDATASTRUCT*)lParam;
9.4 ()
strncpy(request, (char*)pCds->lpData, pCds->cbData);
strcpy(eventName[N], request);
sprintf(suffix, "_%d", N);
strcat(eventName[N], suffix);
// hEvtRecToServ[N] - " N- "
hEvtRecToServ[N] = CreateEvent(NULL, FALSE, FALSE, eventName[N]);
if (!N) {
// hEvtRecToServ
for (i = 0; i < MAX_N; ++i)
hEvtRecToServ[i] = hEvtRecToServ[0];
// ,
hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, 4 * 1024, "SharedData");
// " " " "
hEvtServIsFree = CreateEvent(NULL, FALSE, TRUE, "ServerIsFree");
hEvtServIsDone = CreateEvent(NULL, FALSE,FALSE, "ServerIsDone");
//
tm.hwndParent = hWnd;
hThread = CreateThread(NULL, 0, ThreadFunc, &tm, 0, NULL);
}
//
hwndClient = FindWindow(NULL, request);
cds.dwData = N;
cds.lpData = &eventName[N];
cds.cbData = strlen(eventName[N]);
SendMessage(hwndClient, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds);
if (N < MAX_N) N++;
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
if (N) {
char text[40];
sprintf(text, " : %d", N);
TextOut(hDC, 10, 20, text, strlen(text));
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
CloseHandle(hFileMap);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
DWORD WINAPI ThreadFunc(LPVOID lpv)
{
477
478
9.
ThreadManager* pTm = (ThreadManager*)lpv;
HWND hParent = pTm->hwndParent;
static PVOID pView;
char suffix[40];
int k;
char text[100];
DWORD dw;
while (1) {
// " "
dw = WaitForMultipleObjects(MAX_N, hEvtRecToServ, FALSE, INFINITE);
switch (dw) {
case WAIT_FAILED:
MessageBox(hParent, " WaitForMultipleObjects",
"ServerApp", MB_OK);
return 0;
default:
k = dw - WAIT_OBJECT_0; //
//
pView = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
// text
strcpy(text, (PTSTR)pView);
// "",
sprintf(suffix, " - %s\0",
eventName[k]);
strcat(text, suffix);
//
strcpy((PTSTR)pView, text);
UnmapViewOfFile(pView);
// hEvtServIsDone
SetEvent(hEvtServIsDone);
break;
}
}
return 0;
}
//////////////////////////////////////////////////////////////////////
.
WM_COPYDATA. ClientApp,
, , "
C", (
). request ,
N.
eventName[N]. ""
hEvtRecToServ[N] eventName[N].
N ,
:
hEvtRecToServ
hEvtRecToServ[0]. , WaitForMultipleObjects, "
hEvtRecToServ, .
hFileMap SharedData.
,
CreateFileMapping, 4 .
479
. , "
, .
ThreadFunc. "
.
WM_COPYDATA,
eventName[N] , WM_COPYDATA. " (. . 9.3).
ThreadFunc . "
" hEvtRecToServ, "
. "
,
SetEvent, hEvtServIsDone "
. , ,
.
ClientApp
ClientApp 9.5.
,
IDR_MENU1. Link to server "
IDM_LINK.
9.5. ClientApp
//////////////////////////////////////////////////////////////////////
// ClientApp.cpp
#include <windows.h>
#include <stdio.h>
#include "resource.h"
#include "KWnd.h"
#define
#define
#define
#define
MAX_LEN_REQUEST 80
MAX_LEN_EVTNAME 88
TIMER_ID 1
TIMER_PERIOD 1000
480
9.
return (msg.wParam);
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
COPYDATASTRUCT* pCds;
COPYDATASTRUCT cds;
static char request[MAX_LEN_REQUEST];
static char eventName[MAX_LEN_EVTNAME];
static char text[100];
static char msgSended[256];
static char msgReceived[256];
HWND hwndServer;
static BOOL isLinkToServer;
static BOOL bServerIsDone = FALSE;
static HANDLE hFileMap; // " "
static PVOID pView;
DWORD dw0, dw1;
static int count = 0;
switch (uMsg)
{
case WM_CREATE:
isLinkToServer = FALSE;
msgSended[0] = 0;
msgReceived[0] = 0;
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_LINK: //
sprintf(request, "ClientApp");
cds.lpData = &request;
cds.cbData = strlen(request);
hwndServer = FindWindow(NULL, "ServerApp");
if (!hwndServer) {
MessageBox(hWnd, " !", "ClientApp", MB_OK);
break;
}
SendMessage(hwndServer, WM_COPYDATA, (WPARAM)hWnd,
(LPARAM)&cds);
break;
}
break;
case WM_COPYDATA: //
pCds = (COPYDATASTRUCT*)lParam;
// -
strncpy(eventName, (char*)pCds->lpData, pCds->cbData);
9.5 ()
// -
hEvtRecToServ = OpenEvent(EVENT_ALL_ACCESS, FALSE, eventName);
hEvtServIsFree = OpenEvent(EVENT_ALL_ACCESS, FALSE, "ServerIsFree");
hEvtServIsDone = OpenEvent(EVENT_ALL_ACCESS, FALSE, "ServerIsDone");
// ,
hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,
"SharedData");
SetWindowText(hWnd, eventName);
isLinkToServer = TRUE;
InvalidateRect(hWnd, NULL, TRUE);
SetTimer(hWnd, TIMER_ID, TIMER_PERIOD, NULL);
break;
case WM_TIMER:
// " "
//
dw0 = WaitForSingleObject(hEvtServIsFree, TIMER_PERIOD / 2);
switch (dw0) {
case WAIT_OBJECT_0:
//
pView = MapViewOfFile(hFileMap,
FILE_MAP_WRITE, 0, 0, 0);
// " "
sprintf((PTSTR)pView, "%d\0", ++count);
//
sprintf(msgSended, " : \t\t%s", (PTSTR)pView);
UnmapViewOfFile(pView);
InvalidateRect(hWnd, NULL, FALSE);
SetEvent(hEvtRecToServ); // hEvtRecToServ
// " "
dw1 = WaitForSingleObject(hEvtServIsDone, TIMER_PERIOD / 2);
switch (dw1) {
case WAIT_OBJECT_0:
//
pView = MapViewOfFile(hFileMap,
FILE_MAP_READ, 0, 0, 0);
//
sprintf(msgReceived, " : \t\t%s",
(PTSTR)pView);
UnmapViewOfFile(pView);
bServerIsDone = TRUE;
// " "
SetEvent(hEvtServIsFree);
InvalidateRect(hWnd, NULL, FALSE);
break;
case WAIT_TIMEOUT: return 0;
case WAIT_FAILED:
MessageBox(hWnd, " hEvtServIsDone",
"ClientApp", MB_OK);
return 0;
}
case WAIT_TIMEOUT: return 0;
481
482
9.
case WAIT_FAILED:
MessageBox(hWnd, " hEvtServIsFree",
"ClientApp", MB_OK);
return 0;
}
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
if (isLinkToServer) {
sprintf(text, "
eventName);
TextOut(hDC, 20, 20, text,
TabbedTextOut(hDC, 20, 40,
NULL, 20);
}
if (bServerIsDone) {
bServerIsDone = FALSE;
TabbedTextOut(hDC, 20, 60,
NULL, 20);
}
%s",
strlen(text));
msgSended, strlen(msgSended), 0,
msgReceived, strlen(msgReceived), 0,
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
UnmapViewOfFile(pView);
CloseHandle(hFileMap);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
, ,
Link to server.
(case IDM_LINK), WM_COPYDATA, "
request.
" WM_COPYDATA,
:
" eventName;
", hEvtRecToServ,
hEvtServIsFree, hEvtServIsDone ( hEvtRecToServ "
, );
SharedData ("
);
eventName;
TIMER_PERIOD.
483
.
WM_TIMER,
WaitForSingleObject, . , "
, " .
, .
" hEvtRecToServ. "
. hEvtServIsDone,
, .
,
.
. 9.4 ServerApp ClientApp.
,
, "
Create Open . , ,
.
.
. , , "
484
9.
N ,
. ,
STARTUPINFO PROCESS_INFORMATION:
# define N 1000
STARTUPINFO si[N];
PROCESS_INFORMATION pi[N];
int iProc = 1; //
, ,
:
iProc++;
ZeroMemory( &pi[iProc], sizeof(pi[iProc]) );
ZeroMemory( &si[iProc], sizeof(si[iProc]) );
si[iProc].cb = sizeof(si);
CreateProcess( NULL, "ServProcess.exe", NULL, NULL, FALSE,
0, NULL, NULL, &si[iProc], &pi[iProc]);
iProc . "
, . ,
N1 " (
iProc 0).
"
.
, , , "
:
DWORD dwExitCode;
for (i = 0; i < N; ++i) {
if (pi[i].hProcess) {
GetExitCodeProcess (pi[i].hProcess, &dwExitCode);
if (dwExitCode != STILL_ACTIVE) {
CloseHandle(pi[i].hThread);
CloseHandle(pi[i].hProcess);
pi[i].hProcess = 0;
}
}
}
. GetExitCodeProcess "
, pi[i].hProcess? ,
CloseHandle
.
?
, "
[5]. "
. ,
.
,
,
485
,
.
, "
:
, "
.
" .
, ,
.
, ,
. " " "
.
, Win32, :
(userinterface threads);
(worker threads).
"
.
Windows", "
WinMain WndProc.
, , "
.
ThreadFunc ServerApp.
"
.
, . "
,
COM", .
, Windows Explorer.
. ,
, "
. " Explorer ,
.
, ,
.
: "
.
486
10
10.
. ,
, ,
, ,
. ,
,
.
Win32 API ,
,
.
.
, Windows
, Windows
.
, (
, , 1 30 1).
,
.
, , Windows
.
Win32 API
rdtsc
.
Windows
Windows ,
.
1
,
.
487
,
Windows. ,
, ,
100 .
, , ,
( Intel Celeron CPU 2,0
Microsoft Windows 2000), ,
GetSystemTimeAdjustment, 15,625 .
Windows
GetTickCount. ,
.
.
Windows
UTC (Universal Time Coordinated).
UTC .
GetSystemTime:
VOID GetSystemTime(LPSYSTEMTIME lpSystemTime);
SYSTEMTIME,
lpSystemTime. SYSTEMTIME
, , , , , , .
, , ,
, .
GelLocalTime,
, GetSystemTime.
, ,
SetSystemTime SetLocalTime.
488
10.
,
, GetTimeZoneInformation SetTimeZoneInformation.
,
, Windows.
,
, Windows.
, GetSystemTime
.
, ,
,
( C++).
GetTickCount GetSystemTime,
, ,
1 . ,
:
int t1 = GetTickCount();
// ...
int t2 = GetTickCount();
int elapsedTime = t2 t1;
, , 15,625 .
, 2
.
(QueryPerformanceCounter),
,
rdtsc.
Win32 API
. QueryPerformanceFrequency
:
BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency);
,
. ,
64 LARGE_INTEGER
1
,
.
489
lpFrequency. LARGE_INTEGER
32 LowPart, HighPart 64 QuadPart:
typedef union _LARGE_INTEGER {
struct {
DWORD LowPart;
LONG HighPart;
};
LONGLONG QuadPart;
} LARGE_INTEGER;
64
, LowPart ( 32 ) HighPart
( 32 ).
, QueryPerformanceCounter,
:
BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount);
lpPerformanceCount.
LARGE_INTEGER freq;
LARGE_INTEGER count_t1;
LARGE_INTEGER count_t2;
freq:
QueryPerformanceFrequency(&freq);
:
QueryPerformanceCounter(&count_t1);
// ...
QueryPerformanceCounter(&count_t2);
double dt = count_t2.QuadPart - count_t1.QuadPart;
double elapsedTime = 1000 * dt / freq.QuadPart;
//
?
freq.QuadPart.
,
freq.QuadPart 3 579 545 . ,
1/3579545 , 0,279
279 .
(0,279 )
GetTickCount (15 625 ), .
Intel Pentium1
,
.
RDTSC
Pentium III,
TSC (Time Stamp Counter).
1
490
10.
64 ,
. ( RESET)
TSC .
.
rdtsc (read time stamp counter)
,
EDX:EAX. C++
:
unsigned __int64 GetCycleCount(void) {
_asm rdtsc
}
rdtsc,
:
_asm _emit 0x0F
_asm _emit 0x31
60 3 ,
, Sleep.
.
TSC:
unsigned __int64 t_start;
unsigned __int64 t_stop;
t_start = GetCycleCount();
Sleep(1000);
t_stop = GetCycleCount() - t_start - overhead;
double nCyclePer1microSec = t_stop / 1000000.;
Sleep 1000 .
TSC GetCycleCount
Sleep . ,
t_stop, ,
. overhead ,
GetCycleCount,
. t_stop,
, nCyclePer1microSec, ,
.
:
t_start = GetCycleCount();
// ...
t_stop = GetCycleCount() - t_start - overhead;
double elapsedTime = t_stop / nCyclePer1microSec; //
,
overhead.
, ,
, .
491
. [8]. ,
,
.
. ,
, .
: .
,
.
.
: , ,
.
,
, .
,
.
, .
12 36 .
, [8], .
,
rdtsc, .
, ,
. , Visual Studio 6.0
. : (Win32
Debug) (Win32 Release). ,
, !
,
.
overhead,
GetCycleCount. ,
t_start = GetCycleCount();
//
t_stop = GetCycleCount() - t_start;
t_stop. ,
overhead.
,
. , 88, 100,
84, 320. , ,
, . ,
, 84, ,
.
, overhead
. ,
.
492
10.
TSC .
Sleep.
1, ,
:
timeBeginPeriod(1);
Sleep(20);
, .
timeBeginPeriod(1), MSDN,
, 1 .
, Sleep.
timeEndPeriod(1), ,
.
timeBeginPeriod timeEndPeriod
:
#include <Mmsystem.h>
winmm.lib2.
KTimer,
.
KTimer 10.1.
[6], ,
.
main.cpp
KTimer.
10.1. KTimer
//////////////////////////////////////////////////////////////////////
// KTimer.h
#ifndef KTIMER_H
#define KTIMER_H
#pragma warning(disable : 4035)
typedef enum { Msec, Usec, Ns_100, Ns_10, Nsec } TimeUnit;
static int et[10];
inline unsigned __int64 GetCycleCount(void) {
_asm
rdtsc
}
class KTimer {
__int64 t_start;
__int64 t_stop;
int overhead;
// -
double nCyclePer1nanoSec;
double nCyclePer10nanoSec;
double nCyclePer100nanoSec;
10.1. ()
double nCyclePer1microSec;
double nCyclePer1milliSec;
double divizor; //
public:
KTimer(void) {
// overhead
overhead = 0;
for (int i = 0; i < 10; ++i) {
t_start = GetCycleCount();
et[i] = GetTick();
}
overhead = et[0];
for (i = 1; i < 10; ++i)
if (et[i] < overhead) overhead = et[i];
//
timeBeginPeriod(1);
Sleep(20);
Start();
Sleep(1000);
t_stop = GetCycleCount() - t_start - overhead;
nCyclePer1nanoSec
= t_stop /
nCyclePer10nanoSec = t_stop /
nCyclePer100nanoSec = t_stop /
nCyclePer1microSec = t_stop /
nCyclePer1milliSec = t_stop /
timeEndPeriod(1);
divizor = nCyclePer1milliSec;
1000000000.;
100000000.;
10000000.;
1000000.;
1000.;
//
}
void SetUnit(TimeUnit unit) {
switch (unit) {
case Msec: divizor = nCyclePer1milliSec; break;
case Usec: divizor = nCyclePer1microSec; break;
case Nsec: divizor = nCyclePer1nanoSec; break;
case Ns_10: divizor = nCyclePer10nanoSec; break;
case Ns_100: divizor = nCyclePer100nanoSec; break;
}
}
inline void Start(void) { t_start = GetCycleCount(); }
inline int GetTick(void) {
return (int)(GetCycleCount() - t_start - overhead);
}
inline double GetTime(void) {
t_stop = GetCycleCount() - t_start - overhead;
return t_stop / divizor;
}
inline int GetTickPerUsec(void) { return (int)nCyclePer1microSec; }
inline void uDelay(int uSec) {
int tElapsed = 0;
SetUnit(Usec);
493
494
10.
Start();
while ( tElapsed < uSec)
tElapsed = (int)GetTime();
}
int GetOverhead() { return overhead; }
};
#endif /* KTIMER_H */
//////////////////////////////////////////////////////////////////////
// Main.cpp
#include <windows.h>
#include <Mmsystem.h>
#include <fstream>
#include <iomanip>
using namespace std;
#include "KWnd.h"
#include "KTimer.h"
KTimer timer1;
KTimer timer2;
KTimer timer3;
#define N 5000000
int dTicks[N]; // TSC
double grossWorkQuant[N]; // ()
ofstream flog;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
MSG msg;
KWnd mainWnd(" KTimer", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
int i, No = 0;
char text[200];
double netWorkQuant; // ()
double sleepQuant;
// ""
double totalTime;
// for
switch (uMsg)
{
case WM_CREATE:
flog.open("flog.txt");
timer3.Start();
495
10.1. ()
timer2.Start();
for (i = 0; i < N; ++i) {
timer1.Start();
// ...
dTicks[i] = timer1.GetTick();
if (dTicks[i] > 0) {
grossWorkQuant[i] = timer2.GetTime();
timer2.Start();
}
}
totalTime = timer3.GetTime();
flog << " dTicks 0\n";
flog << "-----------------------------------------------------\n";
flog << "
No
i
dTicks
sleepQuant workQuant\n";
flog << "
()
()\n";
flog << "-----------------------------------------------------\n";
flog.flags(ios::fixed);
for (i = 0; i < N; ++i) {
if (dTicks[i]) {
No++;
sleepQuant = (double)dTicks[i] / timer1.GetTickPerUsec() / 1000.;
netWorkQuant = grossWorkQuant[i] - sleepQuant;
flog << setw(8) << No << setw(10) << i << setw(10)
<< dTicks[i] << setw(12) << setprecision(5) << sleepQuant
<< setw(10) << setprecision(3) << netWorkQuant << endl;
}
}
flog << "-----------------------------------------------------\n";
flog << " : " << totalTime << " " << endl;
flog.close();
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
sprintf(text, "overhead = %d,
CPU speed: %d Mhz\0\n",
timer1.GetOverhead(), timer1.GetTickPerUsec());
TextOut(hDC, 20, 10, text, strlen(text));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
KTimer, KTimer.h,
.
timer:
KTimer timer;
496
10.
:
timer.Start();
// ...
double elapsedTime = timer.GetTime();
timer .
, (
Start) SetUnit.
TimeUnit,
1 , 1 , 100 , 10 , 1 . ,
2 100 (.
).
GetTime GetTick,
, TSC.
Windows .
KTimer uDelay,
, .
.
main.cpp,
KTimer. KTimer:
timer1, timer2 timer3.
WM_CREATE.
, Windows.
. for, N ,
.
timer1.Start() timer1.GetTick(). GetTick
, ,
. dTicks[i] > 0,
Windows. , .
dTicks[i] ,
. timer2
grossWorkQuant[i] ,
. ,
.
totalTime for timer3.
, dTicks
grossWorkQuant, ,
flog.txt. , dTicks[i]
.
, for, TSC
,
netWorkQuant.
KTimer ,
N, 100 000 ( totalTime 9 ),
Windows dTicks
1.
1
, KTimer
, .
497
N = 5 000 000 ( )
, 10.2.
10.2. flog.txt N = 5 000 000
dTicks 0
No
i
dTicks
sleepQuant workQuant
()
()
1
82410
709236
0.35128
7.302
2
435817
3977324
1.96995
30.884
3
589957
46776
0.02317
13.646
4
770080
772092
0.38241
15.588
5
770977
352
0.00017
0.078
6
1299726
39176
0.01940
46.395
7
1479784
793520
0.39303
15.590
8
2357842
128812
0.06380
77.717
9
2471843
16792
0.00832
9.917
10
3068285
328824
0.16286
52.490
11
3772097
39672
0.01965
62.321
12
3952201
691372
0.34243
15.589
13
4128673
280
0.00014
15.379
14
4480734
37272
0.01846
31.130
15
4660754
6874012
3.40466
15.591
16
4801332
481832
0.23865
12.205
17
4978235
460724
0.22819
15.370
:
446.926
, ,
, 10.2, .
KTimer
.
KTimer.h,
#include "KTimer.h" ,
.
winmm.lib.
.
,
while. ,
, 500 .
,
2 ?
, , ,
.
. , ,
498
10.
KTimer.
Sleep
Sleep:
VOID Sleep(DWORD dwMilliseconds);
,
.
, ,
MSDN . , ,
10.3.
10.3. SleepTest1
//////////////////////////////////////////////////////////////////////
// SleepTest.cpp
#include <windows.h>
#include <stdio.h>
#include <Mmsystem.h>
#include "KWnd.h"
#include "KTimer.h"
KTimer timer;
#define SLEEP_TIME
#define N 100
double realTimeInterval[N];
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
MSG msg;
KWnd mainWnd("SleepTest", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static int x, y;
winmm.lib (. ).
499
10.3. ()
char text[200];
int i;
double minT, maxT, amount;
switch (uMsg)
{
case WM_CREATE:
//timeBeginPeriod(1);
// #1
Sleep(20);
// #2
for (i = 0; i < N; ++i) {
timer.Start();
Sleep (SLEEP_TIME);
realTimeInterval[i] = timer.GetTime();
}
//timeEndPeriod(1);
// #3
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
sprintf(text, " SLEEP_TIME = %d", SLEEP_TIME);
TextOut(hDC, 0, 20, text, strlen(text));
x = 15; y = 40;
for (i = 0; i < 20; ++i) {
sprintf(text, "%.2f\0", realTimeInterval[i]);
TextOut(hDC, x, y, text, strlen(text));
y += 16;
}
// min max
minT = maxT = amount = realTimeInterval[0];
for (i = 1; i < N; ++i) {
if (realTimeInterval[i] < minT)
minT = realTimeInterval[i];
if (realTimeInterval[i] > maxT)
maxT = realTimeInterval[i];
amount += realTimeInterval[i];
}
sprintf(text, "minT = %.2f, maxT = %.2f, average = %.2f\0",
minT, maxT, amount / N);
TextOut(hDC, x, y, text, strlen(text));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
500
10.
Sleep
timer KTimer.
WM_CREATE.
N for.
realTimeInterval.
WM_PAINT ,
.
.
SLEEP_TIME.
. 10.1 SLEEP_
TIME.
10.1. , Sleep
SLEEP_TIME,
,
,
9,6
21,64
15,63
15,625
11,74
21,81
15,62
15,625
10
9,7
21,54
15,68
15,625
16
25,28
37,16
31,25
31,25
20
25,26
37,24
31,25
31,25
40
40,94
52,71
46,87
46,875
100
103,43
115,30
109,36
109,375
1000
1000,63
1002,32
1000,76
1000
, ,
Sleep, ,
(15,625 ).
Sleep(20),
#2. , Sleep(SLEEP_TIME)
realTimeInterval[0],
. SLEEP_TIME
80 %, 1000 10 %.
, MSDN.
, , ,
Sleep (.
KTimer).
, Sleep
, timeBegin
Period(1), Windows.
,
1 .
, timeEndPeriod(1)
.
501
, 10.3 ,
#1 #3, . ,
, , . 10.2.
10.2. , Sleep
timeBeginPeriod(1)
SLEEP_TIME,
1
2
3
5
10
20
100
1000
1,66
2,78
3,75
5,38
10,26
20,21
100,20
999,85
4,33
3,07
4,06
7,11
12,93
20,80
100,95
1001,81
1,98
2,93
3,91
5,87
10,78
20,51
100,57
1000,34
( 10 )
,
, . 10.1.
uDelay KTimer
, Sleep
. ,
uDelay KTimer. , ,
SleepTest (. 10.3)
.
#define U_SEC
//
KTimer:
KTimer timer1;
,
WM_CREATE, :
timer1.SetUnit(Usec);
timer.SetUnit(Usec);
for (i = 0; i < N; ++i) {
timer.Start();
timer1.uDelay(U_SEC);
realTimeInterval[i] = timer.GetTime();
}
U_SEC.
, . 10.3.
, KTimer
rdtsc, Pentium III. , QTimer.
502
10.
1
2
5
10
50
100
1000
1,20
2,19
5,14
10,14
50,20
100,15
1000,15
1,25
2,22
5,18
10,16
50,29
100,24
1679,37
1,21
2,20
5,15
10,15
50,27
100,23
1007,03
QTimer
QTimer , KTimer.
. 10.4 .
10.4. QTimer
//////////////////////////////////////////////////////////////////////
// QTimer.h
#ifndef QTIMER_H
#define QTIMER_H
#pragma warning(disable : 4035)
typedef enum { Msec, Usec, Ns_100, Ns_10, Nsec } TimeUnit;
class QTimer {
LARGE_INTEGER freq;
LARGE_INTEGER count_beg;
LARGE_INTEGER count_end;
LONGLONG ll_c_beg;
LONGLONG ll_c_end;
long d_tic;
double dt;
DWORD lowPart;
LONG highPart;
// -
double nCyclePer1nanoSec;
double nCyclePer10nanoSec;
double nCyclePer100nanoSec;
double nCyclePer1microSec;
double nCyclePer1milliSec;
double divizor; //
public:
QTimer(void) {
//
timeBeginPeriod(1);
Sleep(20);
BOOL success = QueryPerformanceFrequency(&freq);
if (!success)
10.4. ()
MessageBox(NULL, " QueryPerformance ",
0, MB_OK | MB_ICONSTOP);
lowPart = freq.LowPart;
highPart = freq.HighPart;
//
nCyclePer1nanoSec
= freq.LowPart / 1000000000.;
nCyclePer10nanoSec = freq.LowPart / 100000000.;
nCyclePer100nanoSec = freq.LowPart / 10000000.;
nCyclePer1microSec = freq.LowPart / 1000000.;
nCyclePer1milliSec = freq.LowPart / 1000.;
timeEndPeriod(1);
divizor = nCyclePer1milliSec; //
}
void SetUnit(TimeUnit unit) {
switch (unit) {
case Msec: divizor = nCyclePer1milliSec; break;
case Usec: divizor = nCyclePer1microSec; break;
case Nsec: divizor = nCyclePer1nanoSec; break;
case Ns_10: divizor = nCyclePer10nanoSec; break;
case Ns_100: divizor = nCyclePer100nanoSec; break;
}
}
inline void Start(void) { QueryPerformanceCounter(&count_beg); }
inline long GetTick(void) {
QueryPerformanceCounter(&count_end);
ll_c_beg = count_beg.QuadPart;
ll_c_end = count_end.QuadPart;
d_tic = ll_c_end - ll_c_beg;
return d_tic;
}
inline double GetTime(void) {
QueryPerformanceCounter(&count_end);
ll_c_beg = count_beg.QuadPart;
ll_c_end = count_end.QuadPart;
d_tic = ll_c_end - ll_c_beg;
return d_tic / divizor;
}
inline int GetTickPerUsec(void) { return (int)nCyclePer1microSec; }
inline void uDelay(int uSec) {
int tElapsed = 0;
SetUnit(Usec);
Start();
while ( tElapsed < uSec)
tElapsed = (int)GetTime();
}
503
504
10.
};
#endif /* QTIMER_H */
//////////////////////////////////////////////////////////////////////
QTimer , KTimer,
KTimer.
Windows ,
.
SetTimer:
UINT_PTR SetTimer(
HWND hWnd,
UINT_PTR nIDEvent,
UINT uElapse,
TIMERPROC lpTimeProc
);
//
//
//
//
- WM_TIMER
, hWnd, ,
. NULL,
.
, nIDEvent, ,
( ).
,
, , enum
#define. . hWnd
NULL, nIDEvent .
, uElapse, ,
() 1 4 294 967 295 , 50 .
, Windows
WM_TIMER. WM_TIMER
hWnd, lpTimeProc NULL,
lpTimeProc .
hWnd NULL,
.
SetTimer , .
,
, KillTimer:
BOOL KillTimer(HWND hWnd, UINT_PTR uIDEvent);
hWnd , .
hWnd,
SetTimer.
.
, ,
, , SetTimer (
, ).
505
, hWnd
SetTimer, lpTimeProc NULL.
, ,
WM_TIMER.
, .
1 , 1 .
#define:
#define TIMER_SEC 1
#define TIMER_MIN 2
WinMain,
WM_CREATE
:
SetTimer(hWnd, TIMER_SEC, 1000, NULL);
SetTimer(hWnd, TIMER_MIN, 60000, NULL);
wParam WM_TIMER
, WM_TIMER
:
case WM_TIMER:
switch (wParam) {
case TIMER_SEC:
//
break;
case TIMER_MIN:
//
break;
}
break;
, , :
KillTimer(hWnd, TIMER_SEC);
KillTimer(hWnd, TIMER_MIN);
, WM_TIMER
uElapse,
.
.
, .
,
, .
, 15,625 ,
, ,
15,625 , 31,25 , 46,875 , 62,5 . .
WM_TIMER, Intel
506
10.
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static int x, y;
char text[200];
int i;
double minT, maxT, amount;
static int count = -1;
switch (uMsg)
{
case WM_CREATE:
SetTimer(hWnd, ID_TIMER, TIME_PERIOD, NULL);
break;
case WM_TIMER:
if (count >= 0 && count < N)
realTimeInterval[count] = timer.GetTime();
timer.Start();
count++;
507
10.5. ()
if (count == N)
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
sprintf(text, " TIME_PERIOD = %d", TIME_PERIOD);
TextOut(hDC, 0, 20, text, strlen(text));
/* , 10.3 */
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
KillTimer(hWnd, ID_TIMER);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
. 10.4.
10.4.
TIME_PERIOD,
1
10
20
40
100
1000
,
,
14,79
15,09
30,47
46,18
108,90
1000,07
16,16
16,17
32,07
47,56
110,10
1015,70
15,62
15,62
31,26
46,88
109,38
1000,86
15,625
15,625
31,25
46,875
109,375
1000
,
. ,
. . ,
. .
,
1 . ,
100 0,52503,38 .
, ,
WM_TIMER .
1
508
10.
,
.
,
. . WM_TIMER
.
WM_PAINT,
. GetMessage WM_TIMER
,
.
,
, ,
, WM_TIMER .
WM_TIMER WM_PAINT .
WM_TIMER, Windows
WM_TIMER. Windows
WM_TIMER .
WM_TIMER.
0,52503,38
109,375 .
503,38 ,
WM_TIMER .
, 43,5 .
0,52
108,855 WM_TIMER (
WM_MOVING ),
0,52 .
12.1 ( 12).
WM_TIMER
. Windows
.
(callback),
1:
VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent,
DWORD dwTime) {
// WM_TIMER
}
, :
static int idTimer;
TimeProc .
509
:
idTimer = SetTimer(NULL, NULL, TIME_PERIOD, (TIMERPROC)TimerProc);
TIME_PERIOD , .
KillTimer(NULL, idTimer);
,
, ,
. , WM_TIMER,
, ,
, .
Windows
, , ,
.
.
winmm.lib1
, , :
#include <Mmsystem.h>
timeGetDevCaps
.
TIMECAPS tc;
timeGetDevCaps(&tc, sizeof(TIMECAPS));
tc.wPeriodMin tc.wPeriodMax
,
. , ,
1 1 000 000 .
timeBeginPeriod timeEndPeriod,
.
.
MSDN timeBeginPeriod(tc.wPeriodMin)
, .
, ,
.
(timeEndPeriod),
.
1
510
10.
timeBeginPeriod timeEndPeriod
Sleep.
,
.
timeSetEvent timeKillEvent
.
. Windows
, .
timeSet
Event:
MMRESULT timeSetEvent(UINT uDelay, UINT uResolution,LPTIMECALLBACK lpTimeProc,
DWORD dwUser, UINT fuEvent);
uDelay .
.
, ,
.
uResolution
. , .
,
. ,
,
uResolution,
.
lpTimeProc ,
. fuEvent
TIME_CALLBACK_EVENT_SET TIME_CALLBACK_EVENT_PULSE,
lpTimeProc .
dwUser , lpTimeProc,
. ,
.
, fuEvent .
:
TIME_ONESHOT
uDelay
TIME_PERIODIC
uDelay
fuEvent ,
Windows :
TIME_CALLBACK_FUNCTION
lpTimeProc (
)
TIME_CALLBACK_EVENT_SET
SetEvent lpTimeProc
TIME_CALLBACK_EVENT_PULSE
PulseEvent (
) lpTimeProc
511
timeSetEvent
. ,
NULL.
,
timeKillEvent .
timeKillEvent
, timeSetEvent.
,
lpTimeProc. 10.6.
10.6. MmTimerTest
//////////////////////////////////////////////////////////////////////
// MmTimerTest.cpp
#include <windows.h>
#include <stdio.h>
#include <Mmsystem.h>
#include <fstream>
using namespace std;
#include "KWnd.h"
#include "KTimer.h"
ofstream flog;
KTimer timer;
enum UserMsg { UM_READY = WM_USER+1 };
#define TIME_PERIOD 1
#define N 1000
double realTimeInterval[N];
void CALLBACK TimeProc(UINT, UINT, DWORD, DWORD, DWORD);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
flog.open("flog.txt");
MSG msg;
KWnd mainWnd("MM timer - test", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
flog.precision(3);
for (int i = 0; i < N; ++i)
flog << realTimeInterval[i] << endl;
flog.close();
return msg.wParam;
}
//====================================================================
512
10.
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
char text[200];
int i;
const int i0 = 30; //
double minT, maxT, amount;
static MMRESULT mmResult;
switch (uMsg)
{
case WM_CREATE:
//timeBeginPeriod(1);
// #1
513
10.6 ()
{
static int count = -1;
HWND hwnd = reinterpret_cast<HWND>(dwUser);
if (count >= 0 && count < N)
realTimeInterval[count] = timer.GetTime();
timer.Start();
count++;
if (count == N) {
InvalidateRect(hwnd, NULL, TRUE);
SendMessage(hwnd, UM_READY, 0, 0);
}
}
//////////////////////////////////////////////////////////////////////
, timeSetEvent
DWORD. TimeProc
InvalidateRect SendMessage.
TIME_PERIOD.
,
, i0 . i0
30. , ,
.
, 1 ,
:
minT = 0.649, maxT = 1.973, average = 1.00.
,
.
? , flog.txt,
N .
, 1,941,966,
1 ,
40 . .
Windows 40 1
. , 0,649,
1000 , 1,3.
, 1,949, ,
: 1,3 0,649.
0,9710,999.
TIME_PERIOD
. 10.5.
10.5.
TIME_PERIOD,
0,649
1,973
1,000
1,177
3,424
2,000
514
10.
TIME_PERIOD,
4,061
6,289
5,000
10
9,220
11,278
10,000
50
49,165
51,288
50,001
100
99,065
100,589
99,999
1000
999,747
1000,256
1000,001
#1
#2. , ,
timeBeginPeriod(1) .
. timeBeginPeriod(1)
! ,
timeBeginPeriod ,
.
.
,
. ,
. , 100
0,52 503,38 .
MmTimerTest
:
minT = 99.57,
, ,
.
Windows ,
.
.
, ,
TimeProc .
,
TIME_PERIOD, TimeProc
, .
, ,
?
, , ,
.
.
515
11
DLL
516
11. DLL
, sprintf, strlen, fopen .
. DLL , ,
, .
.
. DLL
. , ,
, DLL,
.
. ,
Microsoft
Visual Basic, ++. Visual Basic
DLL, ++, .
DLL ,
(, ),
.
, DLL
COM1.
, , DLL
, DLL.
:
: EXE
DLL .
(
DLL ).
. , .
, (,
) DLL .
DLL
DLL .
DLL
.
, .
. , DLL
. DLL ,
. , DLL
DLL .
1
DLL
517
DLL,
.
, , DLL,
, . DLL
, , DLL,
.
, DLL ,
. ,
DLL VirtualAlloc,
, , DLL
. , DLL
.
, , DLL
. ,
VirtualFree .
, DLL
DllMain, .
DLL
DLL , ,
,
DLL. DLL ,
.
DLL MyLib.dll,
void Print(LPCTSTR text);
MessageBox. ,
,
.
Print ,
, MyLib.dll, ,
.
, DLL
__declspec(dllexport). ,
extern "C", C++
.
(mangling) , C++.
, ++ . , .
, extern "C",
MyLib.dll Print
?Print@@YAXPBD@Z. DLL
.
518
11. DLL
11.1 MyLib.dll.
11.1. MyLib
//////////////////////////////////////////////////////////////////////
// MyLib.h - DLL-
#ifndef _MYLIB_H
#define _MYLIB_H
#include <windows.h>
#define EXPORT extern "C" __declspec(dllexport)
//
EXPORT void Print(LPCTSTR text);
#endif
// _MYLIB_H
//////////////////////////////////////////////////////////////////////
// MyLib.cpp - DLL-
#include <stdio.h>
#include "MyLib.h"
int count = 0;
EXPORT void Print(LPCTSTR text)
{
count++;
char title[40];
sprintf(title, "MyLib: Print: %d", count);
MessageBox(NULL, text, title, MB_OK);
}
//////////////////////////////////////////////////////////////////////
#ifndef #endif.
,
.
EXPORT,
.
! DLL Visual
C++ 6.0, Win32 Dynamic Link Library1.
FileNew
New Project. :
, MyLib;
;
Win32 Dynamic-Link Library;
OK.
Win32 Dynamic-Link Library Step 1 of 1
An empty DLL project Finish.
Win32 Application.
DLL
519
, MyLib.h MyLib.cpp
(F7).
?
, Debug. :
MyLib.dll DLL , ;
MyLib.lib LIB , ,
DLL. LIB , ,
, .
DLL ,
.
.
DLL
DLL: ) , ) , ) .
DLL
, DLL,
:
H DLL (
, ).
.
LIB .
( ,
).
.
LIB ,
, .
,
DLL . DLL ,
.
.
?
EXE
:
.
, DLL
. , DLL
DLL. ,
,
.
.
520
11. DLL
EXE DLL
,
.
, DLL
:
, .
.
Windows.
Windows.
, PATH.
, DLL,
ImplClient, Print MyLib.dll.
11.2.
11.2. ImplClient
//////////////////////////////////////////////////////////////////////
// ImplClient.cpp
#include <windows.h>
#include "MyLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
Print("Hello!");
Print("The experiment was a success!");
Print("By!");
return 0;
}
//////////////////////////////////////////////////////////////////////
DLL
521
, Visual Studio,
? ,
, Output. F10
.
,
F10. (
) Output :
Loaded
Loaded
Loaded
Loaded
Loaded
, , MyLib.dll
ntdll.dll.
, DLL
.
:
DLL ,
.
DLL ,
, :
A required DLL file MyLib.dll was not found DLL
.
DLL
. DLL
.
DLL
, DLL.
DLL :
1. DLL LoadLibrary (
LoadLibraryEx). hLib
HMODULE, DLL.
2. GetProcAddress
. GetProcAddress
hLib, C
522
11. DLL
.
. , ,
.
3. ,
, FreeLibrary.
, .
, DLL
.
, Windows
.
, DLL,
ExplClient, Print
MyLib.dll. 11.3.
11.3. ExplClient
//////////////////////////////////////////////////////////////////////
// ExplClient.cpp
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
// DLL
HMODULE hLib;
//
hLib = LoadLibrary("MyLib.dll");
if (!hLib) {
MessageBox(NULL, " MyLib.dll ", "Error", MB_OK);
return 1;
}
// MYPROC - , ,
// DLL
typedef void (*MYPROC) (LPCTSTR str);
// MYPROC
MYPROC pMyProc;
// Print
pMyProc = (MYPROC)(GetProcAddress(hLib,"Print"));
if (!pMyProc) {
MessageBox(NULL, " DLL Print", "Error", MB_OK);
return 1;
}
// Print DLL
pMyProc("Hello!");
pMyProc("The experiment was a success!");
pMyProc("By!");
//
FreeLibrary(hLib);
return 0;
}
//////////////////////////////////////////////////////////////////////
DLL
523
DLL
,
. , Visual Studio
, .
DLL (delayload DLL) DLL,
,
. DLL
:
DLL,
, DLL
. DLL
, DLL .
,
. , DLL
, .
.
DLL ,
,
.
, DLL
, ,
( MyLib.lib).
,
delayimp.lib. ,
/delayload:MyLib.dll.
:
_delayLoadHelper;
MyLib.dll ,
;
, MyLib.dll;
DLL _delayLoadHelper.
524
11. DLL
DLL
_delayLoadHelper. ,
, LoadLibrary, GetProcAddress.
DLL , _delayLoadHelper , DLL
. , DLL
.
DelayLoadClient, , 11.4,
ImplClient:
11.4. DelayLoadClient
//////////////////////////////////////////////////////////////////////
// DelayLoadClient.cpp
#include <windows.h>
#include "MyLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
Print("Hello!");
Print("The experiment was a success!");
Print("By!");
return 0;
}
//////////////////////////////////////////////////////////////////////
, MyLib.dll
. DLL Print("Hello!")
F10 Output :
Loaded symbols for 'F:\ProgWinApi\DelayLoadClient\Debug\MyLib.dll'
Loaded 'C:\WINNT\system32\user32.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\GDI32.DLL', no matching symbolic information found.
Print
MyLib.dll . , ,
!
DLL
525
DLL
, ,
, , . . DLL
. ,
DLL , , ,
, !
, . .
DLL, ,
DLL , *.cpp
*.rc.
5.
. ,
MyDll.dll, , MyDll.
,
(, )
MyDll.rc.
resource.h, ,
MyDll.rc. resource.h
#include ,
MyDll.dll.
resource.h,
. , DLL,
,
.
DLL
resource.h MyDll.h.
, DLL
/noentry. , DLL ,
DllMain.
,
ImplClient ( 11.2), , ,
DLL. : MyResEng.dll
, MyResRus.dll .
MyResEng.dll. :
1. Win32 Dynamic-Link Library MyResEng.
2. , Insert ResourceString
TableNew.
3. :
IDS_1
Hello!
IDS_2
IDS_3
By!
526
11. DLL
6. resource.h MyResEng.h.
7. ( FileView) MyResEng.rc
MyResEng.h.
8. ProjectSettingsLinkProject Options
/noentry.
9. (F7).
Debug MyResEng.dll.
*.lib , .
MyResRus.dll MyResRus.
, :
IDS_1
IDS_2
IDS_3
, MyResRus.rc
MyResRus.h. MyResRus.dll.
DllResClient.
1. Win32 Application DllResClient.
2. DllResClient.cpp ,
11.5, MyLib.h, MyResEng.h MyResRus.h.
11.5. DllResClient
//////////////////////////////////////////////////////////////////////
// DllResClient.cpp
//-------------------------------------------------------------------// :
//
DllResClient.exe Eng
-
//
DllResClient.exe Rus
-
//-------------------------------------------------------------------#include <windows.h>
#include "MyLib.h"
#include "MyResEng.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
char cmdLine[100];
strcpy(cmdLine, lpCmdLine);
HMODULE hLib;
if (!strcmp(cmdLine, "Eng"))
hLib = LoadLibraryEx("MyResEng.dll", 0, LOAD_LIBRARY_AS_DATAFILE);
else if (!strcmp(cmdLine, "Rus"))
hLib = LoadLibraryEx("MyResRus.dll", 0, LOAD_LIBRARY_AS_DATAFILE);
else {
MessageBox(NULL, " ",
"Error", MB_OK);
return 0;
}
char buf[100];
LoadString(hLib, IDS_1, buf, 99);
Print(buf);
527
/
11.5. ()
LoadString(hLib, IDS_2, buf, 99);
Print(buf);
LoadString(hLib, IDS_3, buf, 99);
Print(buf);
return 0;
}
//////////////////////////////////////////////////////////////////////
,
, .
Eng, ,
Rus .
, DLL
LoadLibraryEx, LoadLibrary.
LoadLibraryEx ,
LOAD_LIBRARY_AS_DATAFILE , DLL
. ,
DLL .
Debug
MyResEng.dll, MyResRus.dll MyLib.dll. DllResClient.exe
Eng,
Rus.
, DllResClient.exe,
,
ImplClient!
/
,
. , DLL
,
.
: DLL
, , DLL
.
DLL
DllMain.
:
DLL (
DLL);
, DLL, ;
, , DLL;
DLL ( DLL).
DllMain :
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
// DLL-
528
11. DLL
DWORD fdwReason,
LPVOID lpvReserved
//
//
);
.
, hinstDLL, DLL,
, , DLL.
, ,
hinstDLL .
, fdwReason, :
DLL_PROCESS_ATTACH
, DLL
,
LoadLibrary.
DLL_THREAD_ATTACH
, .
DLL, .
DllMain .
DLL_THREAD_DETACH
, .
DllMain .
DLL_PROCESS_DETACH
, DLL
:
) DLL; )
FreeLibrary; ) .
DLL_PROCESS_ATTACH, ,
DLL. lpvReserved ,
.
, :
, DllMain DLL_PROCESS_ATTACH,
DllMain DLL_THREAD_ATTACH.
DLL LoadLibrary,
DllMain .
DllMain ,
TerminateThread TerminateProcess.
DllMain
, :
(TLS)
529
// ,
break;
case DLL_PROCESS_DETACH:
//
break;
}
return TRUE; //
}
DLL
, (TLS).
DllMain.
DllMain 11.7.
(TLS)
, , DLL,
, . ,
DLL, . DLL
,
. .
, , MtClient ( 11.6),
MyLib.dll.
11.6. MtClient
//////////////////////////////////////////////////////////////////////
// MtClient.cpp
#include <windows.h>
#include "MyLib.h"
DWORD WINAPI ThreadFuncA(LPVOID);
DWORD WINAPI ThreadFuncB(LPVOID);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
HANDLE hThreadA = CreateThread(NULL, 0, ThreadFuncA, 0, 0, NULL);
HANDLE hThreadB = CreateThread(NULL, 0, ThreadFuncB, 0, 0, NULL);
MessageBox(NULL, " ?", "WinMain", MB_OK);
return 0;
}
//====================================================================
DWORD WINAPI ThreadFuncA(LPVOID lpv)
{
Print(" : !");
Print(" : !");
Print(" : !");
return 0;
530
11. DLL
}
//====================================================================
DWORD WINAPI ThreadFuncB(LPVOID lpv)
{
Print(" : Hello!");
Print(" : The experiment was a success!");
Print(" : By!");
return 0;
}
//////////////////////////////////////////////////////////////////////
( WinMain)
ThreadFuncA ThreadFuncB.
DLL Print.
Win32 Application MtClient
MtClient.cpp MyLib.h.
MyLib.lib.
MyLib.lib.
Debug MyLib.dll
EXE . ,
MessageBox:
N
MyLib: Print: 1
: !
MyLib: Print: 2
: Hello!
WinMain
, , ,
. MessageBox
. ,
, .
, Print
. , ,
, .
, OK ,
, Print (
).
count MyLib.cpp.
, ,
, ,
DLL , .
,
. , count
DLL .
,
,
.
, Win32 API
(Thread Local Storage TLS).
: ) TLS, ) TLS.
(TLS)
531
TLS
TLS 11.2.
,
TLS.
, .
. 11.2. TLS
TLS ,
. ,
. ,
, ,
0, 1, 2, 3.
TlsAlloc:
gdwTlsIndex = TlsAlloc();
TlsAlloc
, gdwTlsIndex.
( ) 1.
gdwTlsIndex
.
: , ,
.
532
11. DLL
pGlobData , ,
, . ,
. ,
TLS . ,
, ,
.
:
, :
struct GlobData {
int x;
int y;
int count;
// . . .
char buffer[256];
};
:
GlobData* pGlobData;
(heap) GlobData.
, ,
LocalAlloc:
pGlobData = (GlobData*)LocalAlloc(LPTR, sizeof(GlobData));
pGlobData TLS
TlsSetValue:
TlsSetValue(gdwTlsIndex, pGlobData);
TLS,
TlsGetValue:
GlobData* pGlobData = (GlobData*)TlsGetValue(gwTlsIndex);
pGlobData
GlobData , .
. TlsFree,
(TLS)
533
gdwTlsIndex. TlsFree
free.
TLS .
. DLL
, .
MyMtLib, , MyLib,
.
, MyLib
text :
MyLib: Print: N
N , Print.
, , Print
, ,
count .
MyLib
.
MessageBox, Print,
. ,
Print:
.
MessageBox ,
. .
:
text, Print,
;
title ,
;
x, y, .
.
MyMtLib ( 11.7).
Print MyMtLib : ) InitMyMtLib,
; ) PrintBoxDlgProc, ; )
DllMain, /
.
MyMtLib ,
TRACE,
Output. KWndEx.cpp (.
8.4 8).
534
11. DLL
11.7. MyMtLib
//////////////////////////////////////////////////////////////////////
// MyMtLib.h
#include <windows.h>
#define EXPORT extern "C" __declspec(dllexport)
EXPORT void Print(LPCTSTR text);
EXPORT void InitMyMtLib(int x, int y);
//////////////////////////////////////////////////////////////////////
// MyMtLib.cpp
#include <stdio.h>
#include "MyMtLib.h"
#include "KWndEx.h"
#include "resource.h"
struct GlobData {
int x;
int y;
int count;
char title[100];
char buffer[256];
};
HINSTANCE hInstDll;
DWORD gdwTlsIndex;
BOOL CALLBACK PrintBoxDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
//====================================================================
EXPORT void Print(LPCTSTR text)
{
//
DWORD threadID = GetCurrentThreadId();
TRACE("Print: %X, text = '%s'\n",
threadID, text);
// , gdwTlsIndex
GlobData* pGlobData = (GlobData*)TlsGetValue(gdwTlsIndex);
pGlobData->count++;
sprintf(pGlobData->title, "MyMtLib: Print: %d", pGlobData->count);
strncpy(pGlobData->buffer, text, 99);
DialogBox(hInstDll, MAKEINTRESOURCE(IDD_PRINT_BOX), NULL, PrintBoxDlgProc);
}
//====================================================================
EXPORT void InitMyMtLib(int x, int y)
{
// , gdwTlsIndex
GlobData* pGlobData = (GlobData*)TlsGetValue(gdwTlsIndex);
pGlobData->x = x;
pGlobData->y = y;
pGlobData->count = 0;
}
//====================================================================
BOOL CALLBACK PrintBoxDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
RECT r;
(TLS)
11.7. ()
GlobData* pGlobData = (GlobData*)TlsGetValue(gdwTlsIndex);
switch (uMsg) {
case WM_INITDIALOG:
SetWindowText(hDlg, pGlobData->title);
SetWindowText(GetDlgItem(hDlg, IDC_EDIT1), pGlobData->buffer);
GetWindowRect(hDlg, &r);
MoveWindow(hDlg, pGlobData->x, pGlobData->y,
r.right - r.left, r.bottom - r.top, TRUE);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
//====================================================================
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
GlobData* pGlobData;
hInstDll = hinstDLL;
DWORD threadID;
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
//
TRACE("DllMain: DLL, hinstDLL = %X\n", hinstDLL);
// TLS-
if ((gdwTlsIndex = TlsAlloc()) == 0xFFFFFFFF)
return FALSE;
TRACE("DllMain: gdwTlsIndex = %d \n",
gdwTlsIndex);
break;
case DLL_THREAD_ATTACH: //
//
threadID = GetCurrentThreadId();
TRACE("DllMain: , threadID = %X\n", threadID);
if (TlsGetValue(gdwTlsIndex) == NULL) // TLS
{
//
pGlobData = (GlobData*)LocalAlloc(LPTR, sizeof(GlobData));
535
536
11. DLL
// TLS- pGlobData
TlsSetValue(gdwTlsIndex, pGlobData);
//
TRACE("DllMain: %X\n", pGlobData);
TRACE("DllMain: %X %d\n", pGlobData,
gdwTlsIndex);
}
break;
case DLL_THREAD_DETACH:
//
threadID = GetCurrentThreadId();
TRACE("DllMain: , threadID = %X\n", threadID);
//
pGlobData = (GlobData*)TlsGetValue(gdwTlsIndex);
if (pGlobData != NULL)
LocalFree((HLOCAL)pGlobData);
break;
case DLL_PROCESS_DETACH:
//
TRACE("DllMain: DLL\n");
// TLS-index.
TlsFree(gdwTlsIndex);
break;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
, LocalAlloc, ,
LPTR. LPTR ,
: LMEM_FIXED LMEM_ZEROINIT.
LMEM_FIXED ()
.
LMEM_ZEROINIT
.
Win32 Dynamic-Link Library MyMtLib
MyMtLib.h, MyMtLib.cpp, KWndEx.h KWndEx.cpp.
.
ID IDD_PRINT_BOX
System menu. 1/3.
Cancel, OK
.
Edit box,
: , Border ,
Multiline, AutoHScroll, Read only .
Debug MyMtLib.dll
MyMtLib.lib.
MtTlsClient ( 11.8)
.
(TLS)
537
11.8. MtTlsClient
//////////////////////////////////////////////////////////////////////
// MtTlsClient.cpp
#include <windows.h>
#include "MyMtLib.h"
DWORD WINAPI ThreadFuncA(LPVOID);
DWORD WINAPI ThreadFuncB(LPVOID);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
HANDLE hThreadA = CreateThread(NULL, 0, ThreadFuncA, 0, 0, NULL);
HANDLE hThreadB = CreateThread(NULL, 0, ThreadFuncB, 0, 0, NULL);
MessageBox(NULL, " ?", "WinMain", MB_OK);
return 0;
}
//====================================================================
DWORD WINAPI ThreadFuncA(LPVOID lpv)
{
InitMyMtLib(400, 350);
Print(" : !");
Print(" : !");
Print(" : !");
return 0;
}
//====================================================================
DWORD WINAPI ThreadFuncB(LPVOID lpv)
{
InitMyMtLib(660, 350);
Print(" : Hello!");
Print(" : The experiment was a success!");
Print(" : By!");
return 0;
}
//////////////////////////////////////////////////////////////////////
538
11. DLL
DllMain: , threadID =
DllMain: 143900
DllMain: 143900 3
Print: AEC, text = ' :
...
Print: 8E0, text = ' :
Print: AEC, text = ' :
Print: 8E0, text = ' :
Print: AEC, text = ' :
DllMain: , threadID = 8E0
DllMain: , threadID = AEC
DllMain: DLL
AEC
Hello!'
!'
The experiment was a success!'
!'
By!'
. 11.3. Print
TLS
.
__declspec(thread), :
__declspec(thread) int count = 0;
.
__declspec(thread) Visual C++.
,
, .tls.
TLS
. ,
.tls
TLS . ,
EXE , DLL .
TLS ,
.
TLS ,
.
TLS ,
__declspec(thread) DLL,
LoadLibrary. , Access violati
on. DLL TLS.
539
12
.
Windows.
,
.
,
MSDN.
,
. ,
. ,
, .
,
.
,
.
. ,
: ) ; ) ,
, .
12.1.
Win32 API:
(CreatePatternBrush) (SetClassLong)
(FillRect) .
1 (CreateCompatibleDC) DDB
(SelectObject)
(BitBlt).
540
12.
(CreateEllipticRgn, SelectClipRgn)
,
BitBlt.
(SetWorldTransform)
.
SaveDC RestoreDC,
.
12.1. BounceBall1
//////////////////////////////////////////////////////////////////////
// BounceBall.cpp
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include "KWnd.h"
#include "resource.h"
#define Pi 3.14159265
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawBall(HWND, HDC, HBITMAP, BITMAP, FLOAT, FLOAT, int);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG lpMsg;
KWnd mainWnd("Bounce ball", hInstance, nCmdShow, WndProc);
while (GetMessage(&lpMsg, NULL, 0, 0))
TranslateMessage(&lpMsg);
DispatchMessage(&lpMsg);
}
return (lpMsg.wParam);
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static FLOAT x = 0, y = 0;
//
static FLOAT dX, dY;
//
static int alpha = 0;
// ,
static HDC hDC;
//
static HBRUSH hBkBrush; //
HBITMAP hBmpBkgr;
//
static HBITMAP hBmpBall; //
static BITMAP bm;
//
RECT rect;
//
RECT rBall;
// ,
switch(uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
1
12.1. ()
GetClientRect(hWnd,
&rect);
dX = rect.right / 100.;
dY = rect.bottom / 50.;
// (0.1 )
SetTimer(hWnd, 1, 100, NULL);
hBmpBkgr = LoadBitmap((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDB_STONE));
hBkBrush = CreatePatternBrush(hBmpBkgr);
SetClassLong(hWnd, GCL_HBRBACKGROUND, (LONG)hBkBrush);
hBmpBall = LoadBitmap((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDB_BALL));
GetObject(hBmpBall, sizeof(bm), (LPSTR)&bm);
SetGraphicsMode(hDC, GM_ADVANCED);
break;
case WM_TIMER:
GetClientRect(hWnd, &rect);
//
SetRect(&rBall, (int)x, (int)y, (int)x + bm.bmWidth,
(int)y + bm.bmHeight);
FillRect(hDC, &rBall, hBkBrush);
//
x += dX;
y += dY;
alpha += 10;
if (alpha > 360) alpha = 0;
// ,
if(x + bm.bmWidth > rect.right || x < 0)
dX = -dX;
if(y + bm.bmHeight > rect.bottom || y < 0)
dY = -dY;
DrawBall(hWnd, hDC, hBmpBall, bm, x, y, alpha);
break;
case WM_DESTROY:
KillTimer(hWnd, 1);
ReleaseDC(hWnd, hDC);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
void DrawBall(HWND hwnd, HDC hdc, HBITMAP hBmp, BITMAP bm, FLOAT x, FLOAT y,
int alpha) {
XFORM xform;
541
542
12.
HRGN hRgn;
//
HDC hBallMemDC = CreateCompatibleDC(hdc);
SelectObject(hBallMemDC,
hBmp);
//
hRgn = CreateEllipticRgn(x, y, x + bm.bmWidth, y + bm.bmHeight);
SelectClipRgn(hdc,
hRgn);
//
xform.eM11 = (FLOAT) cos(alpha * 2 * Pi / 360);
//
xform.eM12 = (FLOAT) sin(alpha * 2 * Pi / 360);
//
xform.eM21 = (FLOAT) -sin(alpha * 2 * Pi / 360);
//
xform.eM22 = (FLOAT) cos(alpha * 2 * Pi / 360);
//
xform.eDx = x + bm.bmWidth / 2.;
// x
xform.eDy = y + bm.bmHeight / 2.;
// y
//
SaveDC(hdc);
BOOL ret = SetWorldTransform(hdc, &xform);
BitBlt(hdc, -bm.bmWidth/2, -bm.bmHeight/2,
bm.bmWidth, bm.bmHeight, hBallMemDC, 0, 0, SRCCOPY);
RestoreDC(hdc, -1);
SelectClipRgn(hdc, NULL);
DeleteObject(hRgn);
DeleteDC(hBallMemDC);
}
//////////////////////////////////////////////////////////////////////
SetGraphicsMode
(GM_ADVANCED).
.
DrawBall SetWorldTransform, xform
.
. SetWorldTransform
SaveDC,
RestoreDC.
WM_TIMER. , ,
.
,
,
. BMP
. Stone.bmp,
Microsoft Office1. , Ball.bmp,
, MS Paint,
256 2.
3 5. ,
1
Ball.bmp BounceBall,
, www.piter.com.
DIB
543
. 12.1. BounceBall
, . ,
.
:
(FillRect) (BitBlt).
, FillRect.
,
, .
,
.
,
. ,
. : )
; ) .
.
12.2,
.
544
12.
12.2. BounceBallAdv
//////////////////////////////////////////////////////////////////////
// BounceBallAdv.cpp
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include "KWnd.h"
#include "resource.h"
#define Pi 3.14159265
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawBall(HWND, HDC, HDC, HBITMAP, BITMAP, FLOAT, FLOAT, int);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG lpMsg;
KWnd mainWnd("Bounce ball", hInstance, nCmdShow, WndProc);
while (GetMessage(&lpMsg, NULL, 0, 0)) {
TranslateMessage(&lpMsg);
DispatchMessage(&lpMsg);
}
return (lpMsg.wParam);
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
static FLOAT x = 0, y = 0; //
static FLOAT dX, dY; //
static int alpha = 0; // ,
static HDC hDC;
//
static HBRUSH hBkBrush; //
HBITMAP hBmpBkgr;
//
static HBITMAP hBmpBall; //
static BITMAP bm;
//
RECT rect; //
RECT rBall; // ,
static HDC hMemDcFrame;
// ( )
static HBITMAP hBmpFrame; //
static int count = 0;
switch(uMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
GetClientRect(hWnd, &rect);
dX = rect.right / 100.;
dY = rect.bottom / 50.;
// (0.1 )
11.2 ()
SetTimer(hWnd, 1, 100, NULL);
hBmpBkgr = LoadBitmap((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDB_STONE));
hBkBrush = CreatePatternBrush(hBmpBkgr);
SetClassLong(hWnd, GCL_HBRBACKGROUND, (LONG)hBkBrush);
hBmpBall = LoadBitmap((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDB_BALL));
GetObject(hBmpBall, sizeof(bm), (LPSTR)&bm);
hMemDcFrame = CreateCompatibleDC(hDC);
hBmpFrame = CreateCompatibleBitmap(hDC, rect.right, rect.bottom);
SelectObject(hMemDcFrame, hBmpFrame);
SetGraphicsMode(hMemDcFrame, GM_ADVANCED);
break;
case WM_SIZE:
GetClientRect(hWnd, &rect);
hBmpFrame = CreateCompatibleBitmap(hDC, rect.right, rect.bottom);
DeleteObject(SelectObject(hMemDcFrame, hBmpFrame));
// hMemDcFrame
BitBlt(hMemDcFrame, 0, 0, rect.right, rect.bottom, hDC, 0, 0,
SRCCOPY);
break;
case WM_TIMER:
GetClientRect(hWnd, &rect);
if (!count) { // hMemDcFrame
BitBlt(hMemDcFrame, 0, 0, rect.right, rect.bottom, hDC, 0, 0,
SRCCOPY);
count++;
}
//
SetRect(&rBall, x, y, x + bm.bmWidth, y + bm.bmHeight);
FillRect(hMemDcFrame, &rBall, hBkBrush);
//
x += dX;
y += dY;
alpha += 10;
if (alpha > 360) alpha = 0;
// ,
if(x + bm.bmWidth > rect.right || x < 0)
dX = -dX;
if(y + bm.bmHeight > rect.bottom || y < 0)
dY = -dY;
DrawBall(hWnd, hDC, hMemDcFrame, hBmpBall, bm, (int)x, (int)y, alpha);
break;
case WM_DESTROY:
KillTimer(hWnd, 1);
ReleaseDC(hWnd, hDC);
545
546
12.
DeleteDC(hMemDcFrame);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
void DrawBall(HWND hwnd, HDC hdc, HDC hMemFrameDC, HBITMAP hBmp,
BITMAP bm, FLOAT x, FLOAT y, int alpha) {
XFORM xform;
HRGN hRgn;
//
HDC hMemDcBall = CreateCompatibleDC(hdc);
SelectObject(hMemDcBall, hBmp);
//
hRgn = CreateEllipticRgn(x, y, x + bm.bmWidth, y + bm.bmHeight);
SelectClipRgn(hMemFrameDC, hRgn);
//
xform.eM11 = (FLOAT) cos(alpha * 2 * Pi / 360); //
xform.eM12 = (FLOAT) sin(alpha * 2 * Pi / 360); //
xform.eM21 = (FLOAT) -sin(alpha * 2 * Pi / 360); //
xform.eM22 = (FLOAT) cos(alpha * 2 * Pi / 360); //
xform.eDx = x + bm.bmWidth / 2;
// x
xform.eDy = y + bm.bmHeight / 2;
// y
// hMemFrameDC
SaveDC(hMemFrameDC);
BOOL ret = SetWorldTransform(hMemFrameDC, &xform);
BitBlt(hMemFrameDC, -bm.bmWidth/2, -bm.bmHeight/2,
bm.bmWidth, bm.bmHeight, hMemDcBall, 0, 0, SRCCOPY);
RestoreDC(hMemFrameDC, -1);
// hMemFrameDC hdc
RECT rect;
GetClientRect(hwnd, &rect);
BitBlt(hdc, 0, 0, rect.right, rect.bottom, hMemFrameDC, 0, 0, SRCCOPY);
SelectClipRgn(hMemFrameDC, NULL);
DeleteObject(hRgn);
DeleteDC(hMemDcBall);
}
//////////////////////////////////////////////////////////////////////
hMemDcFrame, .
CreateCompatibleDC,
SelectObject hBmpFrame,
.
hMemDcFrame
WM_TIMER.
, count BitBlt
.
547
hMemDcFrame .
WM_SIZE.
,
WM_TIMER.
DrawBall,
hMemFrameDC. DrawBall
,
BitBlt .
BitBlt hMemFrameDC
.
.
.
.
, ,
. ,
, ,
,
.
, ,
.
ARINC
characteristic 708A1.
:
1600 .
.
:
12 ;
512 1536
( ).
5,00 7,82 .
90 /c .
548
12.
,
.
, ,
.
scanAngle 12
. scanAngle ,
0 4095 ,
2048 +2047. 4096 ,
, 360.
digitWeight scanAngle 360 / 4096 =
0,087890625.
PACK_PERIOD ,
( )
:
speedWithPackPeriod
digitWeight
(PACK_PERIOD
1000.)
digitWeight 5 PACK_PERIOD,
speedWithPackPeriod = 17,578/c.
90/c!
,
,
. ,
:
sieveCoeff = ceil(sweepSpeedDue / speedWithPackPeriod);
sweepSpeedDue .
, sweepSpeedDue = 90, PACK_PERIOD = 5
sieveCoeff = 6. ,
.
sweepSpeedDue
. sieveCoeff,
.
(,
, sieveCoeff1 ).
.
.
,
.
,
.
60 +60, .
549
PACK_PERIOD 5 .
{ 15, 30, 60, 90 } .
:
) ; ) ; )
( ); )
.
ArincReceiverBad.
.
ArincReceiverBad.
ToolTip (. 8.4) ArincReceiverBad KwndEx.h KwndEx.cpp.
KTimer (. 10.1) KTimer.h.
.
Link comctl32.lib winmm.lib.
IDR_MENU1.
, . 12.1.
12.1.
IDM_START
IDM_STOP
,
. 12.2.
12.2.
15 /
IDM_SPEED_15
30 /
IDM_SPEED_30
60 /
IDM_SPEED_60
90 /
IDM_SPEED_90
ArincReceiverBad.cpp ,
12.3.
12.3. ArincReceiverBad
//////////////////////////////////////////////////////////////////////
// ArincReceiverBad.cpp
#include <windows.h>
#include <commctrl.h>
#include <Mmsystem.h>
#include <stdio.h>
#include <math.h>
#include "resource.h"
#include "KWndEx.h"
550
12.
#include
"KTimer.h"
//
UpdateStatusBar();
CALLBACK TimerFunc(UINT, UINT, DWORD, DWORD, DWORD);
GetPacket();
//
GetNextAngle();
//
SetColorBeamForth(); // cell
//
void SetColorBeamBack(); // cell
//
void DrawBeam();
//
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWndEx mainWnd("ArincReceiverBad", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 900, 600);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
551
12.3 ()
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HMENU hMenu; //
RECT rect, rcSB;
int aWidths[4];
static MMRESULT mmTimer;
switch (uMsg)
{
case WM_CREATE:
hMenu = GetMenu(hWnd);
SetClassLong(hWnd, GCL_HBRBACKGROUND,
(LONG)CreateSolidBrush(RGB(100, 100, 100)));
sweepSpeedDue = 90;
CheckMenuRadioItem(GetSubMenu(hMenu, 0), IDM_SPEED_15,
IDM_SPEED_90, IDM_SPEED_90, MF_BYCOMMAND);
//
hwndStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd,
ID_STATUSBAR);
aWidths [0] = 205;
aWidths [1] = 355;
aWidths [2] = 610;
aWidths [3] = -1;
SendMessage(hwndStatusBar, SB_SETPARTS, 4, (LPARAM)aWidths);
SendMessage(hwndStatusBar, SB_SIMPLE, FALSE, 0);
digitWeight = 360.0 / 4096;
speedWithPackPeriod = digitWeight / (PACK_PERIOD / 1000.);
sieveCoeff = ceil(sweepSpeedDue / speedWithPackPeriod);
UpdateStatusBar();
GetClientRect(hWnd, &rect);
GetWindowRect(hwndStatusBar, &rcSB);
X0 = rect.right / 2;
Y0 = rect.bottom - (rcSB.bottom - rcSB.top);
//
g_hDC = GetDC(hWnd);
SetColorBeamForth();
break;
case WM_SIZE:
SendMessage (hwndStatusBar, WM_SIZE, wParam, lParam);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_SPEED_15:
sweepSpeedDue = 15;
CheckMenuRadioItem(GetSubMenu(hMenu, 0), IDM_SPEED_15,
IDM_SPEED_90, LOWORD(wParam), MF_BYCOMMAND);
break;
552
12.
case
IDM_SPEED_30:
sweepSpeedDue = 30;
CheckMenuRadioItem(GetSubMenu(hMenu,
0),
IDM_SPEED_15,
IDM_SPEED_90, LOWORD(wParam), MF_BYCOMMAND);
break;
case IDM_SPEED_60:
sweepSpeedDue = 60;
CheckMenuRadioItem(GetSubMenu(hMenu, 0), IDM_SPEED_15,
IDM_SPEED_90, LOWORD(wParam), MF_BYCOMMAND);
break;
case IDM_SPEED_90:
sweepSpeedDue = 90;
CheckMenuRadioItem(GetSubMenu(hMenu, 0), IDM_SPEED_15,
IDM_SPEED_90, LOWORD(wParam), MF_BYCOMMAND);
break;
case IDM_START:
timer.Start();
mmTimer = timeSetEvent(PACK_PERIOD, 0, TimerFunc,
reinterpret_cast<DWORD>(hWnd), TIME_PERIODIC);
if (!mmTimer)
MessageBox(hWnd, "Error of timeSetEvent!", NULL,
MB_OK | MB_ICONSTOP);
break;
case IDM_STOP:
timeKillEvent(mmTimer);
break;
}
sieveCoeff = ceil(sweepSpeedDue / speedWithPackPeriod);
UpdateStatusBar();
break;
case WM_DESTROY:
ReleaseDC(hWnd, g_hDC);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
void UpdateStatusBar()
{
char text[100];
sprintf(text, " : %.0f /", sweepSpeedDue);
SendMessage(hwndStatusBar, SB_SETTEXT, 0, (LPARAM)text);
sprintf(text, ". . : %d", sieveCoeff);
SendMessage(hwndStatusBar, SB_SETTEXT, 1, (LPARAM)text);
sweepTimeDue = 2.*(RIGHT_MARGIN-LEFT_MARGIN) *
(PACK_PERIOD/1000.) / sieveCoeff;
sprintf(text, " :
sweepTimeDue);
%.2f ",
553
12.3 ()
SendMessage(hwndStatusBar,
SB_SETTEXT,
2,
(LPARAM)text);
sprintf(text, " :
sweepTimeFact);
SendMessage(hwndStatusBar, SB_SETTEXT, 3, (LPARAM)text);
%.2f
",
}
//====================================================================
void CALLBACK TimerFunc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1,
DWORD dw2)
{
// -
HWND hwndOwner = reinterpret_cast<HWND>(dwUser);
// ( ,
// -)
GetPacket(); //
DrawBeam(); //
//
for (int i = 1; i < sieveCoeff; ++i) {
GetNextAngle();
DrawBeam();
}
}
//====================================================================
void GetPacket() {
GetNextAngle();
}
//====================================================================
void GetNextAngle() {
char text[100];
if (direction == FORTH)
if (++scanAngle >= RIGHT_MARGIN)
direction = BACK;
SetColorBeamBack();
554
12.
if (i < 128)
else if (i < 256)
else if (i < 384)
else
cell[i]
cell[i]
cell[i]
cell[i]
=
=
=
=
RGB(255, 0, 0);
RGB(0, 255, 0);
RGB(255, 255, 0);
RGB(0, 0, 255);
}
}
//====================================================================
void SetColorBeamBack() {
for (int i = 0; i < 512; ++i) {
if (i < 128)
cell[i] = RGB(0, 0, 255);
else if (i < 256) cell[i] = RGB(255, 255, 0);
else if (i < 384) cell[i] = RGB(0, 255, 0);
else
cell[i] = RGB(255, 0, 0);
}
}
//====================================================================
void DrawBeam() {
x = X0;
y = Y0;
double angle = scanAngle * digitWeight;
double C = cos(Pi * (90 - angle) / 180);
double S = sin(Pi * (90 - angle) / 180);
for (int k = 0; k < 512; ++k) {
x += C;
y -= S;
SetPixel(g_hDC, (int)x, (int)y, cell[k]);
}
}
//////////////////////////////////////////////////////////////////////
.
PACK_PERIOD, 5 .
, ,
10, .
.
5
TimerFunc.
. TimerFunc
. TimerFunc
,
.
TimerFunc
.
GetPacket .
, GetPacket
.
cell.
555
, GetPacket
GetNextAngle.
GetNextAngle
.
scanAngle .
(FORTH), ,
(BACK) .
direction .
SetColorBeamForth SetColorBeamBack, cell
.
, , (
). ,
, .
SetColorBeamForth SetColorBeamBack
, cell GetPacket.
GetNextAngle
.
timer KTimer,
10.
.
DrawBeam.
cell
SetPixel.
g_hDC.
WM_CREATE
WM_DESTROY.
.
().
Windows (Task
Manager), .
Ctrl+Shift+Esc.
.
. ,
.
ArincReceiverBad.
90 /. .
,
. 12.2.
Intel Celeron CPU 2,0 Microsoft Windows
2000.
100 % !
.
, .
556
12.
. 12.2. ArincReceiverBad
, 90 /
.
(2,52 )
(2,28 ).
60 /
60 %, . ,
,
.
,
? SetPixel!
2 , SetPixel ,
1000 .
.
DIB
.
.
DIB 3,
. .
, DIB DIB,
,
GDI. DIB
.
557
DIB CreateDIBSection, :
HBITMAP
hBmp
CreateDIBSection(hdc,
&bmi,
DIB_RGB_COLORS,
&pBits,
NULL,
0);
bmi,
. pBits
DIB.
DIB pBits.
,
(x, y), , .
:
bytePerLine = ((width * bmi.bmiHeader.biBitCount + 31) / 32) * 4;
KDibSection,
DIB. KDibSection
.
ArincReceiver.
ArincReceiverBad (. 12.3) ArincReceiver
.h, .cpp .rc, ArincReceiverBad
ArincReceiver. .
Link comctl32.lib winmm.lib.
KDibSection.h KDibSection.cpp ,
12.4. ArincReceiver.cpp,
12.4.
12.4. ArincReceiver
//////////////////////////////////////////////////////////////////////
// KDibSection.h
#include <windows.h>
class KDibSection {
public:
KDibSection() : pBits(0) {}
BOOL Create(HDC hdc, int _width, int _height);
inline void SetPixel(int x, int
int ind = 3 * x;
((BYTE*)pBits)[y*bytePerLine
((BYTE*)pBits)[y*bytePerLine
((BYTE*)pBits)[y*bytePerLine
}
y, COLORREF color) {
+ ind] = GetBValue(color);
+ ind + 1] = GetGValue(color);
+ ind + 2] = GetRValue(color);
558
12.
//////////////////////////////////////////////////////////////////////
//
KDibSection.cpp
#include "KDibSection.h"
BOOL KDibSection::Create(HDC hdc, int _width, int _height) {
width = _width;
height = _height;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
bytePerLine = ((width * bmi.bmiHeader.biBitCount + 31) / 32) * 4;
hBmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
return (hBmp != NULL);
}
//////////////////////////////////////////////////////////////////////
// ArincReceiver.cpp
#include <windows.h>
#include <commctrl.h>
#include <Mmsystem.h>
#include <stdio.h>
#include <math.h>
#include
#include
#include
#include
"resource.h"
"KWndEx.h"
"KTimer.h"
"KDibSection.h"
/* , 12.3 */
KDibSection dibSect;
/* , 12.3 */
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWndEx mainWnd("ArincReceiver", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 900, 600);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HMENU hMenu; //
RECT rect, rcSB;
559
12.4 ()
int aWidths[4];
static MMRESULT mmTimer;
switch (uMsg)
{
case WM_CREATE:
/* , 12.3
*/
// DIB-
dibSect.Create(g_hDC, rect.right, Y0);
break;
case WM_SIZE:
SendMessage (hwndStatusBar, WM_SIZE, wParam, lParam);
break;
case WM_COMMAND:
/* , 12.3
*/
break;
case WM_DESTROY:
ReleaseDC(hWnd, g_hDC);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
void UpdateStatusBar()
{
/* , 12.3
*/
}
//====================================================================
void CALLBACK TimerFunc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1,
DWORD dw2)
{
// -
HWND hwndOwner = reinterpret_cast<HWND>(dwUser);
// ( ,
// -)
POINT ppt[4]; //
// ppt[0] ppt[3]
ppt[0].y = ppt[3].y = Y0;
if (direction == FORTH) { ppt[0].x = X0 - 1;
ppt[3].x = X0 + 1; }
if (direction == BACK)
{ ppt[0].x = X0 + 1;
ppt[3].x = X0 - 1; }
GetPacket();
DrawBeam();
//
//
560
12.
// ppt[1]
ppt[1].y = y;
if (direction == FORTH) ppt[1].x = x - 1;
if (direction == BACK)
ppt[1].x = x + 1;
//
for (int i = 1; i < sieveCoeff; ++i) {
GetNextAngle();
DrawBeam();
}
// ppt[2]
ppt[2].y = y;
if (direction == FORTH) ppt[2].x = x + 1;;
if (direction == BACK)
ppt[2].x = x - 1;
//
HRGN hRgn = CreatePolygonRgn(ppt, 4, WINDING);
SelectClipRgn(g_hDC, hRgn);
// ( )
dibSect.Draw(g_hDC);
DeleteObject(hRgn);
}
//====================================================================
void GetPacket() {
GetNextAngle();
}
//====================================================================
void GetNextAngle() {
/* , 12.3
*/
}
//====================================================================
void SetColorBeamForth() {
/* , 12.3
*/
}
//====================================================================
void SetColorBeamBack() {
/* , 12.3
*/
}
//====================================================================
void DrawBeam() {
x = X0;
y = Y0;
double angle, C, S;
angle = scanAngle * digitWeight;
C = cos(Pi * (90 - angle) / 180);
S = sin(Pi * (90 - angle) / 180);
for (int k = 0; k < 512; ++k) {
x += C;
y -= S;
// DIB-
dibSect.SetPixel((int)x, (int)y, cell[k]);
}
}
//////////////////////////////////////////////////////////////////////
561
KDibSection KDibSection.h,
KDibSection.cpp.
SetPixel color (x, y)
DIB. SetPixel ,
pBits.
, Draw, DIB
hdc.
dibSect :
KDibSection
dibSect;
DIB WM_CREATE:
dibSect.Create(g_hDC,
rect.right,
Y0);
,
.
DrawBeam GDI SetPixel
dibSect:
dibSect.SetPixel((int)x,
(int)y,
cell[k]);
(
TimerFunc), Draw .
SetPixel ,
Draw,
, width height.
Draw (
) 8 . ,
,
5 . , ,
ArincReceiverBad.
, .
, 5
width height. ,
sieveCoeff .
:
HRGN hRgn = CreatePolygonRgn(ppt, 4, WINDING);
ppt.
. 12.3.
. 12.3. : ) ;
)
562
12.
ppt
TimerFunc.
g_hDC Draw:
dibSect.Draw(g_hDC);
(
KTimer) ,
0,2 .
ArincReceiver,
90/, , 5 %!
, DIB
.
, Windows
, Windows
. 10.
, ArincReceiver,
Windows , .
ArincReceiver ,
.
563
1
Visual C++ 6.0
Integrated Development Environment ( ),
IDE , ,
, .
, Microsoft Visual Studio 6.0,
IDE Microsoft Visual C++ 6.0, .
, Visual C++,
Hello, World!, (project).
( .cpp),
( .h), ( .rc)
,
( .exe).
Visual Studio
. .
(project workspace)
, .
Win32
Application empty project.
.
.
IDE.
Visual C++
Microsoft Visual Studio 6.0Microsoft Visual C++ 6.01. ,
,
.
Visual C++ ,
. 1.1. Visual C++
.
1
564
Visual C++
Microsoft Developer Studio, ,
Visual C++, Visual J, MS Fortran Power Station
.
Visual C++ .
Project Workspace ( )
. (. . 1.1) ,
, .
Editor ( ) .
Output ( ) ,
. ,
.
, Windows,
.
,
IDE. ,
.
IDE.
565
, ,
.
Developer Studio ,
.
Win32 Application empty project.
Win32 Application
:
FileNew.
New Projects.
Win32 Application,
Project Name, , HelloFromMsgBox.
Location1.
, .
OK.
Application
Wizard, Win32 Application Step1 of 1
, .
An empty project Finish.
, D:\MyProjects.
566
, Visual C++
HelloFromMsgBox,
, , .
HelloFromMsgBox.dsw, HelloFromMsgBox.dsp, HelloFromMsgBox.opt, HelloFromMsgBox.ncb.
Debug Release,
. :
HelloFromMsgBox.dsw ,
.
, .
HelloFromMsgBox.dsp ,
. Visual C++ .mak.
HelloFromMsgBox.opt ,
.
Developer Studio,
, .
HelloFromMsgBox.ncb
,
ClassView. ClassView Project Workspace
C++, ,
.
Debug , ,
.
, .exe.
Visual C++
(. . 1.2), .
, Project Workspace Class View File View.
File View.
. HelloFromMsgBox files,
. ,
Source Files, Header Files, Resource Files.
, An empty project.
, .
.
( HelloFromMsgBox.cpp)
. , ,
:
HelloFromMsgBox.cpp
. HelloFromMsgBox.
IDE.
567
:
FileNew.
New.
OK.
Editor
HelloFromMsgBox.cpp. Project Workspace Source
Files . , Source Files
.
HelloFromMsgBox.cpp.
.
Source Files Project Workspace,
Add Files to Folder.
Insert Files into Project . (, HelloFromMsgBox.cpp) OK.
. 1.3. HelloFromMsgBox.cpp
.
, , :
568
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, "Hello, Win32 world!", "Hello from Message Box", MB_OK);
return 0;
}
. Developer Studio
.
, .
.
/
Header Files Project Workspace.
Add Files to Folder.
Insert Files into Project .
, , AnyName.h, OK.
,
Build ,
.
Build:
Compile .
Output.
Build . ,
.
, ,
.
Output. ,
.exe .
Execute ,
.
Compile, Build Execute
Build MiniBar .
Build MiniBar . 1.4.
IDE.
569
Build
, .
Rebuid All.
.
, Build (F7).
Output.
,
:
HelloFromMsgBox.exe - 0 error(s), 0 warning(s).
, Execute
Program (Ctrl+F5).
Go (F5) .
,
.
Visual C++ (Win32
Debug), (Win32 Release).
, .
. ,
. ProjectSettings.
Project Settings. ,
Settings For:.
Win32 Debug, BuildSet Active Configuration
.
, FileClose Work- space.
Visual C++.
,
:
1. Visual C++. File Open Workspace
,
570
ProjectName.dsw. ,
Microsoft Developer Network (MSDN)
,
Microsoft.
MSDN (MSDN Library)
Microsoft Visual Studio 6.0.
,
Win32 API.
MSDN MSDN.
MSDN , IDE Visual C++ Help
. , .
Editor,
C++
F1. MSDN .
MSDN,
. ,
Visual C++ Windows SDK.
Visual C++
.
Visual C++.
, , ,
, .
.
, ,
. ,
.
, , .
.
, .
, . ,
,
.
.
IDE.
571
Windows,
.
, MSDOS.
FileNew. Projects New.
Win32 Console Application,
Project Name,
Location OK.
Buggy.
. ,
3,
1.
Buggy buggy.cpp :
#include <iostream.h>
int main() {
const N = 5;
int a[N] = {1, 2, 3, 4, 5};
float sum, average;
int i;
for (i = 1; i < N; i++)
sum += a[i];
average = sum / N;
cout << "average = " << average << endl;
return 0;
}
.
:
average = -2.14748e+007
,
21 474 800 ( ),
3.0. .
,
, .
,
F9
Insert/Remove BreakPoint Build MiniBar.
. .
.
BuildStart
DebugGo. ,
1
, , .
.
572
.
Editor , .
,
.
Buggy.
for
, F5.
, Build Debug.
Visual Studio . 1.5.
for,
.
Debug
Step Into (F11), Step Over (F10), Step Out (Shift+F11), Run To Cursor (Ctrl+F10)
Stop Debugging (Shift+F5).
.
,
Visual C++, .
. 1.5. Debug
F10, .
, ,
func1(). ,
, F11.
IDE.
573
,
, F10.
, func1(), F11,
, , .
Shift+F11.
.
Ctrl+F10.
Buggy. F10.
:
sum += a[i];
sum,
a, .
:
sum = -1.07374e+008
!!! , , ,
sum, , . !
sum .
Shift+F5,
. :
float sum, average;
sum:
float sum = 0, average;
Build (F7)
Execute Program (Ctrl+F5). :
average = 2.8
, .
. .
for
, F5. F10.
:
sum += a[i];
F10, :
for (i = 1; i < N; i++)
sum .
:
sum = 2.
!!! , sum
a, 1. 2,
a. ,
C++ .
:
for (i = 1; i < N; i++)
574
.
. for:
for (i = 0; i < N; i++)
.
,
average = 3.0.
, .
,
.
Variables Watch
,
(. . 1.5).
Editor, Output. Variables
, Watch .
ViewDebug Windows.
Auto Variables ,
Visual C++. Variables
Context, .
Watch ,
.
Help Visual C++.
IDE Microsoft Visual C++ 6.0 ,
. , , ,
5 7.
Find in Files Context
.
Find in Files
Find in Files ,
. 1.6.
,
.
Find in Files. Find in Files,
.
Match whole word only ( ) / Match
case ( ). Find,
Output
.
IDE.
575
,
,
!
Context
, Access
Violation. ,
.
Context, Variables (. . 1.5)
,
,
.
.
,
. ,
,
. (
), , , .
.
, ,
. ,
A, 1. ,
A :
RECT* pRect;
, ,
A, pRect.
, Show, , ,
:
void A::Show() {
int x0 = pRect->left;
int y0 = pRect->top;
}
!
, A, Show
(unhanded exception),
(. 1.7).
. 1.7.
1
.
, .
576
(F5), OK ,
. 1.8.
. 1.8. Context,
, Context,
A::Show().
, .
pRect,
, ?
!
577
2
Visual Studio.NET
, Microsoft Visual Studio.NET
. IDE Visual Studio.NET
IDE Visual Studio 6.0, 1.
, .
Win32 Application empty project, ,
.
Visual Studio.NET ,
. 2.1. Visual Studio.NET
,
.
578
2. VisualStudio.NET
Win32 Application empty project
.
FileNewProject. New Project,
. 2.2.
579
Application Settings. ,
. 2.6.
Additional options Empty project
Finish. Visual Studio.NET , . 2.7.
580
2. VisualStudio.NET
.
HelloFromMsgBox, ,
. . HelloFromMsgBox.sln
( ), HelloFromMsgBox.vcproj .
, .sln .dsw Visual
C++ 6.0 , , .vcproj .dsp.
,
.
581
582
2. VisualStudio.NET
, :
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, "Hello, Win32 world!", "Hello from Message Box", MB_OK);
return 0;
}
Visual Studio.NET ,
. 2.9.
FileSave.
,
BuildBuild Solution (Ctrl+Shift+B).
Output.
, , . 2.10.
.
DebugStart Without Debugging (Ctrl+F5).
Debug
Start (F5).
583
InsertResource,
Visual Studio 6.0, ProjectAdd
Resource. Add Resource.
, Visual Studio 6.0.
Visual Studio.NET Controls
Toolbox, ViewToolbox.
Studio.NET.
Toolbox .
, .
,
Properties,
Solution Explorer, .
,
Visual Studio 6.0.
584
3. Spy++
3
Spy++
Microsoft Visual Studio 6.0 ( Visual Studio.NET)
Spy++.
, ,
.
Spy++ Visual Studio
6.0. Visual Studio ToolsSpy++.
Spy++ , . 3.1.
. 3.1. Spy++
XXX
. XXX.
Spy XXX ,
.
SpyMessages. Message Options
(. 3.2).
Windows Finder Tool ,
, XXX,
. .
585
3. Spy++
Selected Object :
(Window);
(Text);
(Thread ID);
(Process ID).
OK, Messages (Window)
(. 3.3).
Spy++ ,
. Messages (Window )
:
586
3. Spy++
, . 3.1.
3.1.
PostMessage
SendMessage
SendMessage, (security)
S R (return),
.
,
Spy++ , ,
, . ,
.
, , , Messages
(Window ), .
Message Options Messages
(. 3.4).
. 3.4. Messages
/ :
1. Message Groups ,
,
. , ,
.
2. Messages to View ,
.
.
Spy++ ,
, .
3. Spy++
587
1. . Windows 95. . 1. : BHV
, 1997. 739 .
2. ., . Windows. :
BHV , 1997. 816 .
3. . Microsoft Windows 2000 API. . :
, 2001. 1008 .
4. . Windows 2000. .
: , 2000. 640 .
5. . Windows : Win32
64 Windows. :
, 2001. 752 .
6. . Windows. : , 2002.
1072 .
7. . . Win32 API. .:
, 2001. 312 .
8. . .
. : BHV , 2003. 464 .
9. ., . ++. :
. : , 2004. 265 .
588
3. Spy++
Wait 462
window procedure 42
world space 67
R
region 59
ritical section 460
18
470
459
19
(DLL) 20
79
font 59
font mapping 128
GDI 19, 58
GUI 16
thread 443
thread context 443
Tooltip 391
TrueType 119
TSC 489
174
27
60
216
214
Windows 486
134
UTC 487
272
273
B
bitmap 59
bitmap stretching mode 182
brush 59
Button 323
D
DDB 175
DDK 19
device space 67
dialog box 304
dialog procedure 304
dialog template units 308
DIB 175
DIB 201
E
event 464
H
handle 20
hotkey 273
M
mailslots 470
mapping modes 71
mouse cursor 226
MSMQ 470
mutex 467
V
Virtual Memory Manager
471
VMM 471
543
20
589
442
55
304
304
20
471
18
470
423
66
274
444
35
59
23
KDib 184
KWndEx 408
KDibSection 557
KDocument 146
KTimer 492
KWnd 46
QTimer 502
473
323
356
443
43, 59
65
293
272
Windows
28
28
28
86
460
226
491
124
GetBValue 77
GetGValue 77
GetRValue 77
HIWORD 55
LOWORD 55
MAKEINTRESOURCE
253
PALETTEINDEX 77
PALETTERGB 77
RGB 77
206
67
304
winmm.lib 266
467
304
218
60
Windows
29
18
391
341
26
22, 42
32
(
) 23
33
20
112
159
59
385
443
59, 87
76
243
28
33
443
17
459
491
443
17
563
487
120
174
99
79
59
59, 109
60
428
. . .
AppBrowser
182
71
MM_TEXT 72
441
80
OPAQUE 81
TRANSPARENT 81
441
242
18
466
473
67
22
487
590
214
41
464
65
470
21
PBM_SETPOS 424
PBM_SETRANGE 423
PBM_SETSTEP 424
PBM_STEPIT 424
SB_GETRECT 414
SB_SETMINHEIGHT
415
SB_SETPARTS 414
SB_SETTEXT 414
SB_SIMPLE 414
TB_ADDSTRING 390
TB_AUTOSIZE 391
TBM_GETPOS 431
TBM_SETLINESIZE 430
TBM_SETPAGESIZE
430
TBM_SETRANGE 430
TBM_SETTICFREQ 430
UDM_GETPOS 437
UDM_SETRANGE 437
WM_CHAR 218
WM_COMMAND 284
WM_CONTEXTMENU
293
WM_CTLCOLOREDIT
343
WM_CTLCOLORSTATIC
321
WM_DRAWITEM 325
WM_HSCROLL
430, 437
WM_INITDIALOG 318
WM_INITMENU 284
WM_KEYDOWN 216
WM_KEYUP 216
WM_KILLFOCUS 221
WM_LBUTTONDBLCLK
227
WM_LBUTTONDOWN
227
WM_MENUCHAR 284
WM_MENUSELECT
284, 416
WM_MOUSEMOVE 226
()
WM_MOUSEWHEEL
227
WM_NOTIFY 385
WM_SETFOCUS 221
WM_SETFONT 321
WM_SYSCOMMAND
284
WM_VSCROLL 430, 437
WM_CLOSE 45, 51
WM_COMMAND 51
WM_COPYDATA 474
WM_CREATE 51
WM_DESTROY 46, 51
WM_ERASEBKGND 61
WM_HSCROLL 144
WM_INITDIALOG 51
WM_MOVE 51
WM_NCPAINT 61
WM_PAINT 42, 51, 61
WM_QUIT 24, 41
WM_SIZE 51
WM_TIMER 51
WM_VSCROLL 144
22
23
53
24, 40
344
86
97
19
67
471
413
BITMAP 193
BITMAPFILEHEADER
176
BITMAPINFO 183
BITMAPINFOHEADER
176
CHOOSECOLOR 377
CHOOSEFONT 377
DRAWITEMSTRUCT
325
()
INITCOMMONCONTROLSEX
381
LOGPALETTE 171
NMHDR 392
OPENFILENAME 377
PALETTEENTRY 161
RGBQUAD 180
TBBUTTON 389
TOOLINFO 407
TOOLTIPTEXT 392
COPYDATASTRUCT
474
LOGBRUSH 100
LOGFONT 125
MSG 40
PAINTSTRUCT 61
POINT 40
PROCESS_INFORMATION
448
RECT 44
SCROLLINFO 143
STARTUPINFO 447
SYSTEMTIME 487
TEXTMETRIC 121
WNDCLASSEX 32
XFORM 72
435
489
COLORREF 77
HBRUSH 97
HFONT 124
HGDIOBJ 87
HICON 253
HPEN 87
Windows 20
471
67
214
18
AppendMenu 281
BitBlt 197
591
()
CheckDlgButton 332
CheckRadioButton 333
CreateBitmap 193
CreateBitmapIndirect
193
CreateCaret 219
CreateCompatibleBitmap
194
CreateCompatibleDC
197
CreateDialog 366
CreateDIBitmap 194
CreateDIBSection 201
CreateEnhMetaFile 207
CreateHalftonePalette
168
CreateStatusWindow 413
CreateToolBarEx 390
DeleteMenu 281
DestroyCaret 220
DialogBox 319
DrawMenuBar 283
EndDialog 319
GetDialogBaseUnits 308
GetDlgItem 306
GetDlgItemInt 344
GetDlgItemText 343
GetEnhMetaFileHeader
211
GetMenu 284
GetObject 196
GetSubMenu 284
HideCaret 220
InitCommonControlsEx
380
InsertMenu 281
IsDialogMessage 367
LoadAccelerators 301
LoadBitmap 195
LoadImage 195
LoadLibrary 382
LoadMenu 281
MessageBox 372
OutputDebugString 413
PlayEnhMetaFile 210
RealizePalette 168
RemoveMenu 281
SelectPalette 168
SendDlgItemMessage
342
()
SetDIBitsToDevice 183
SetDlgItemText 344
SetMenu 281
SetMenuDefaultItem 276
SetMenuItemInfo 281
SetStretchBltMode 182
SetWindowText 321
ShowCaret 220
ShowWindow 312
StretchBlt 198
StretchDIBits 181
TrackPopupMenuEx 294
TranslateAccelerator 301
TranslateMessage 218
_beginthreadex 456
AngleArc 85
Arc 84
ArcTo 85
BeginPaint 43, 61
CheckMenuItem 282
CheckMenuRadioItem
283
Chord 106
CloseHandle 442
CombineRgn 111
CreateBrushIndirect 100
CreateCompatibleDC 65
CreateEllipticRgn 109
CreateEllipticRgnIndirect
109
CreateEvent 464
CreateFileMapping 472
CreateFont 125
CreateFontIndirect 128
CreateHatchBrush 98
CreateIC 66
CreateMutex 467
CreatePatternBrush 99
CreatePen 90
CreatePenIndirect 91
CreatePolygonRgn 110
CreatePolyPolygonRgn
110
CreateProcess 447
CreateRectRgn 109
CreateRectRgnIndirect
109
CreateRoundRectRgn 110
CreateSemaphore 466
()
CreateSolidBrush 97
CreateThread 451
CreateWindow 35
CreateWindowEx 38
DefWindowProc 42
DeleteCriticalSection 461
DeleteObject 82
DestroyWindow 46
DispatchMessage 41
DrawFocusRect 105
DrawText 44, 136
DrawTextEx 136, 139
Ellipse 105
EnableMenuItem 283
EndPaint 62
EnterCriticalSection 460
ExtCreatePen 93
ExtTextOut 140
FillRect 104
FindResource 264
FindWindow 474
FrameRect 104
GelLocalTime 487
GetArcDirection 85
GetBkMode 81
GetClassLong 56
GetClientRect 44
GetDC 62
GetDeviceCaps 74
GetDlgCtrlID 306
GetMessage 41
GetModuleHandle
56, 255
GetPixel 78
GetStockObject
82, 88, 124
GetSystemTime 487
GetSystemTimeAdjustment
487
GetTextCharacterExtra 133
GetTextExtentPoint32 134
GetTextFace 129
GetTextMetrics 121
GetTickCount 487
GetWindowDC 62
GetWindowRect 68
InflateRect 102
InitializeCriticalSection
460
InterlockedDecrement 459
592
()
InterlockedIncrement 459
InvalidateRect 64, 260
InvalidateRgn 64
InvertRect 105
KillTimer 504
LeaveCriticalSection 461
LineTo 83
LoadIcon 253
LoadImage 253
LoadResource 264
LoadString 270
LockResource 264
MapViewOfFile 472
MessageBox 26
ModifyMenu 283
ModifyWorldTransform 74
MoveToEx 83
OffsetRect 102
OffsetRgn 111
OpenEvent 465
OpenSemaphore 466
PeekMessage 57
Pie 106
PlaySound 265
PolyBezier 87
PolyBezierTo 87
Polygon 107
Polyline 84
PolylineTo 84
PolyPolygon 108
PolyPolyline 84
PostMessage 54
PostQuitMessage 46
PtInRegion 110
QueryPerformanceCounter
489
()
QueryPerformanceFrequ
ency 488
Rectangle 103
RegisterClass 35
RegisterClassEx 32
ReleaseDC 62
ReleaseSemaphore 466
RestoreDC 73
RoundRect 106
SaveDC 73
ScrollWindow 145
SelectClipRgn 113
SelectObject 82
SendDlgItemMessage 346
SendMessage 54
SendNotifyMessage 54
SetArcDirection 85
SetBkColor 45
SetBkMode 45, 81
SetBrushOrgEx 98
SetClassLong 51
SetCursor 258
SetDCPenColor 89
SetGraphicsMode 73
SetMapMode 71
SetPixel 78
SetPixelV 78
SetPolyFillMode 108
SetPrioriryClass 446
SetRect 102
SetROP2 80
SetTextAlign 130
SetTextCharacterExtra
133
SetTextColor 45
SetTextJustification 134
()
SetThreadPriority 446
SetTimer 504
SetViewportExtEx 71
SetViewportOrgEx 70
SetWindowExtEx 70
SetWindowOrgEx 70
SetWindowRgn 112
SetWorldTransform 67, 73
ShellExecute 268
ShowWindow 39
Sleep 452, 498
TabbedTextOut 131
TextOut 130
timeBeginPeriod 509
timeEndPeriod 509
timeGetDevCaps 509
timeKillEvent 511
timeSetEvent 510
TranslateMessage 41
TryEnterCriticalSection 461
UnmapViewOfFile 472
UpdateWindow 63
WaitForMultipleObjects
463
WaitForSingleObject 462
(CALLBACK) 22
49
DispatchMessage 24
WinMain 25
308
59
98