Вы находитесь на странице: 1из 592

Win32 API.

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

:ra emp : : :upOIpaCO,

:, 8CIplO ,
++, OIIlolll aonc roe: I Wdows.
lIpaIcrxa , ' orpac apaary
are , FC I Wdows

Forms, a6o.I W32 !,

C'I'III8C ctpcII , : OJICO xor O8J[


:. aupom, :upcpa:po: W32 ! 03O.J!R 8Th
om .

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

Hello, world! ............................................ 46


.......................................................................... 49
................................................................ 50
............................................................ 51
Windows .......................................... 52
................................................ 53
..................................................... 54
.................... 55
................................. 55

....................................... 56
Spy++ ............................................................ 57

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

3. GDI. , , ......................... 159


.................................................................................................... 159
........................................ 159

............................................................................... 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

5. Windows- ................................ 242


.................................................................................. 243
............................................................................................. 243
................ 246
.................................................... 250
.............................. 251
................................................. 252
.................................................................................................... 256
..................................................................................... 260
, .................................................... 263

................................................................... 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

10. ..................................................... 486


Windows .......................................................................................... 486
....................................................................................... 487
................................................. 488
...................... 488
RDTSC ............................................................ 489
...................................... 497
Sleep .............................................................. 498
uDelay KTimer ........................................ 501
QTimer ........................................................................................ 502
................................................................................. 504
......................... 504
.......................... 508
........................................................................... 509
timeSetEvent timeKillEvent .................................................... 509
............................................. 511

11. DLL ........ 515


DLL ..................................................... 514
DLL ........................................................................ 517
DLL .............................................................................. 519
DLL ............................................................................. 519
DLL ............................................................................... 521
DLL ..................................................................... 523
DLL .......................................................................... 525
/ .............................................................................. 527
(TLS) ................................................................. 529
TLS ................................................................................ 531
TLS ................................................................................... 538

12

12. ..................................... 539


.................................................................................................. 539
................................................ 539
.......................................................................... 543
................................................................. 547
............ 547
....................................... 548

1. Visual C++ 6.0 ....... 563


IDE. .................................................................. 563
..................................................................... 565
................................. 566
...................................................................... 568
, .................................. 568
......................................................................... 569
..................................................... 569
,
...................................................... 569
........................................................... 570
............................................................................ 570
....................................................... 574

2. Visual Studio.NET .... 577


.......................................................................... 578
......................................................... 580
, ........................................................... 582
................................................................. 583

3. Spy++ ............................. 584


.................................................................. 587
........................................................... 588


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

Windows XP. Visual


Studio 6.0, , 
1.
Microsoft Visual Studio.NET,
,
2.

. 
, , 
.
, ,
, 
. K,
MFC.

, ,
.  
, 
, .

Windows. ,
Windows.
, ,
,
shupak@mail.ru.


, 
comp@piter.com ( , ).
!
, , http://
www.piter.com/download.
 
: http://www.piter.com.

16

1. Hello, World!, Windows

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

1. Hello, World!, Windows

, , , 
. (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

1. Hello, World!, Windows

( ). 
(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, LPCSTR

LPCWSTR

Unicode-2

LPSTR

C-

LPTSTR

LPWSTR, UNICODE, LPSTR

LPWSTR

Unicode-

LRESULT

LONG,

NULL

((void*) 0)

TCHAR

Wchar_t (Unicode-), UNICODE, char

UINT

32-

WPARAM

, wParam,

,

.
, , 
, ,
1

C . 
ANSI. , , 
C.

Unicodec , 
. UNICODE, 
, 2.

22

1. Hello, World!, Windows

. 
, ,
. ,
, .
, :
 , ;


() ;

, .
, 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

1. Hello, World!, Windows

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)

main DOS UNIX,


.
int :
 HINSTANCE hInstance , Windows 
.


HINSTANCE hPrevInstance Win32


1.

LPSTR lpCmdLine , 
, .
, Norton Commander. 
, , 
.
EXE. (
EXE), 
.

, Object.

Windows 3.x, 
.

26

1. Hello, World!, Windows

int nCmdShow ,
ShowWindow. .
WINAPI ,
Win32 . 
, ,
WinMain .
, .
MessageBox, , , 
.
?
?.. :
MessageBox.
,
MessageBox, MSDN1.

F1.
MessageBox .
MessageBox, , ,
. ,
.
2:


int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);




:
hWnd . NULL, 
.

lpText , .

lpCaption ,
.

uType ,
, .
MessageBox 
7. ,
,
.
, Windows. , 
MessageBox,
, .


Microsoft Developer Network (MSDN) , 



Microsoft. MSDN (MSDN Library), 
Microsoft Visual Studio 6.0,
, Win32 API. 
MSDN MSDN.

( ) ,
.

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

1. Hello, World!, Windows

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. Hello, World!, Windows

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

1. Hello, World!, Windows

. , 
, ,
.
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

1. Hello, World!, Windows

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

1. Hello, World!, Windows


int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lParam

//
//
//
//
//
//
//
// ,
//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

1. Hello, World!, Windows

,
, .
, 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

int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,


LPVOID lParam);

, , , 
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

1. Hello, World!, Windows

1.10. nCmdShow ShowWindow

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

typedef struct tagPoint {


LONG x;
LONG y;
} POINT;


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 
,
.


, .

TCHAR char, UNICODE . 


wchar_t (Unicode).

42

1. Hello, World!, Windows

, 
, . 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

1. Hello, World!, Windows

, 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

1. Hello, World!, Windows

?, . 
, 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. Hello, World!, Windows

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

return DefWindowProc(hWnd, uMsg, wParam, lParam);


}
return 0;
}
//////////////////////////////////////////////////////////////////////

:
KWnd 12 . 
, 
.

,
LRESULT. 
WINAPI __stdcall.

, , 
KWnd.

WinMain mainWnd KWnd,


.

WM_CLOSE 
. MessageBox 
.
MB_YESNO : YES NO.
YES IDYES,
DestroyWindow.
( Hello2), 
.
mainWnd. ,


KWnd mainWnd("Hello application", hInstance, nCmdShow, WndProc);


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. Hello, World!, Windows

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

1. Hello, World!, Windows

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.

CreateSolidBrush (RGB (200, 160, 255)) , 


: (200), (160)
(255). .
CreateSolidBrush 2.

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

1. Hello, World!, Windows



.
,
.

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

1. Hello, World!, Windows

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();
// -
}
}

fReadData ifstream. while


fReadData 512
DoSomething. ,
5 , DoSomething 10 .
5335040 / 512 = 10420 , OnPlay
105 .
.
, 
. 
, Windows ,
. Win32 API

Windows

57

PeekMessage.
GetMessage:
BOOL PeekMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);

//
//
//
//
//

, 
. ,
, .
wRemoveMsg :
 PM_NOREMOVE ;
PM_REMOVE .
, OnPlay, PeekMessage,
:


void OnPlay(HWND hWnd) {


MSG message;
while (!fReadData.eof()) {
fReadData.read(buf, 512);
//
if (PeekMessage(&message, hWnd, 0, 0, PM_REMOVE)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
DoSomething();

// -

}
}

PeekMessage , 
, .
ProgressBar,
8.

Spy++
, 
Windows . 
Visual Studio 6 
Spy++.
:
ToolsSpy++.
Spy++ 3.

58

2. GDI

GDI
.
,
,

(graphics device interface (GDI)) 


Win32 API, 
, . Windows
.
GDI, GDI
, 
(. 2.1). GDI gdi32.dll, 
.
Windows, 
.

. 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 :


BOOL InvalidateRgn(HWND hWnd, HRGN hRgn, BOOL bErase);

, , , 
. 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)
. ,

.

(physical device space)


. 
.

, SetWorldTransform.

. . 2.2 
, SetWorldTransform.


. 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

(x, y) (x', y')


:
x' = (x xWO) xVE / xWE + xVO;
y' = (y yWO) yVE / yWE + yVO.

.
 . 
(0, 0, 1, 1). x' = x, y' = y,
.


. (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, dx, dy).


x' = x + dx, y' = y + dy.

. (mx, 0, 0, my, 0, 0). 


x' = mx x, y' = my y.

. (1, 0, 0, 1, 0, 0).
x' = x, y' = y.

. (cos(), sin(), sin(), cos(), 0, 0).


x' = cos() x sin() y y' = sin() x + cos() 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

(DT_PLOTTER, DT_RASDISPLAY, DT_RASPRINTER


)

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

. 2.3. COLORREF, RGB

(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);

//
//
//
//
//
//
//
//

RGB(0x0, 0x0, 0x0);


RGB(0xFF, 0x0, 0x0);
RGB(0x0, 0xFF, 0x0);
RGB(0x0, 0x0, 0xFF);
RGB(0xFF, 0xFF, 0x0);
RGB(0xFF, 0x0, 0xFF);
RGB(0x0, 0xFF, 0xFF);
RGB(0xFF, 0xFF, 0xFF);


, 16 777 216
RGB COLORREF. , 
, 256 .
.
3. 
COLORREF, .
Win32 API PALETTEINDEX PALETTERGB, 
COLORREF. 
. 2.4.

. 2.4. COLORREF, PALETTEINDEX PALETTERGB

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.

Visual C++ 6.0.

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;

width POINT, Windows 


width.x width.y.
, LOGPEN, :
LOGPEN 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 
, . ,

,

SetBrushOrgEx(hDC, xLeft + 1, yTop + 1, NULL);

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

SetRect(&rect, xLeft, yTop, xRight, yBottom);

OffsetRect(&rect, dX, dY);

X
dX Y dY

InflateRect(&rect, dX, dY);

SetRectEmpty(&rect);

rect

CopyRect(&DestRect, &SrcRect);

IntersectRect(&DestRect, &SrcRect1, &SrcRect2);


UnionRect(&DestRect, &SrcRect1, &SrcRect2);

bEmpty = IsRectEmpty(&rect);

bInRect = PtInRect(&rect, point);

, 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);

point POINT. iCount


, iPolyFillMode ALTERNATE
WINDING.
, 
CreatePolyPolygonRgn:
hRgn = CreatePolyPolygon(point, polyCounts, iCount, iPolyFillMode);

PolyPolygon.


,
.
. 2.15 , .
2.15.

BOOL PtInRegion(HRGN hrgn, int X, int Y);

, (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.

BOOL FillRgn(HDC hdc, HRGN hrgn, HBRUSH hbr);

hbr

BOOL PaintRgn(HDC hdc, HRGN hrgn);

BOOL FrameRgn(HDC hdc, HRGN hrgn,


HBRUSH hbr, int nWidth, int nHeight);

hbr.
nWidth,

nHeight

BOOL InvertRgn(HDC hdc, HRGN hrgn);


(
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

American Standard Code for Information Interchange.

, , 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

ANSI American National Standards Institute.

ISO International Organization for Standardization.

116

2. GDI

, .
. , 
932 ( ), 949 ( ) 950 (
) .
2.20. ANSI

0 .. 127

128 .. 255

1250 (Windows Latin2)

ASCII

1251 (Windows Cyrillic)

ASCII

1252 (Windows Latin1)

ASCII

1253

ASCII

1254

ASCII

...

...

...

. 2.24. Windows Latin 1 (1252)

. 2.25. Windows Cyrillic (1251)

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.

Arial Times New Roman 


, Courier New . ,
Times New Roman Courier New 
, Arial .
, ,
(family). . 2.21.
2.21.

(
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:


BOOL GetTextMetrics(HDC hdc, LPTEXTMETRIC lptm);

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

dpi dot per inch ( ).

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)

OEM Original Equipment Manufacturers

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);

breakExtra nBreak. SetTextJustification , 


, ,
TextOut ExtTextOut.
5. ,
TA_LEFT ( ).
TextOut .
, SetTextJustification 
, breakExtra nBreak. 
GetTextExtentPoint32 ,
GetTextExtentPoint32
SetTextJustification(hdc, 0, 0);

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] =
{ "",
" ",
"
"
"
"
};

",
, ",
, ",
, ."

int x = 20, y = 20;


SIZE size;
int nWidth, i;
switch (uMsg)
{
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
GetTextExtentPoint32(hDC, text[5], strlen(text[5]), &size);
nWidth = size.cx;
for (i = 0; i < 6; i++) {
TextJustOut(hDC, x, y, text[i], nWidth);
y += size.cy + 2;
}
EndPaint(hWnd, &ps);

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.30. text1 rect

. 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);

. 2.33. , (\n), 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);

hdc, X, Y, lpString, cbCount ,


TextOut. :
ExtTextOut(hDC, x, y, 0, NULL, lpString, cbCount, NULL);


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:


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

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

, KWnd.h KWnd.cpp ( 1.2


1) Project Workspace
.


public:
BOOL
void
void
void
void
void

147

Open(const char* file);


Initialize(LPTEXTMETRIC tm);
ScrollSettings(HWND hwnd, int width, int height);
UpdateHscroll(HWND hwnd, int xInc);
UpdateVscroll(HWND hwnd, int yInc);
PutText(HWND hwnd, HDC hdc);

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.

WinMain Open doc, 


, FILE_NAME.
README.TXT, Microsoft Visual C++
6.01. ,
.

WS_VSCROLL | WS_HSCROLL, 
KWnd windowStyle.

.

WndProc Initialize doc 


WM_CREATE, ScrollSettings 
WM_SIZE.

WM_VSCROLL doc.UpdateVscroll(hWnd, yInc). WM_HSCROLL


doc.UpdateHscroll(hWnd, xInc).

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

mx = xVE / xWE, my = yVE / yWE, xVE, yVE , xWE, yWE


.

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;
}
//====================================================================

,
.

KWnd.h KWnd.cpp (. 1.2 1).

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

int xMin = tMin * nPixPerMs;


int xMax = tMax * nPixPerMs;
for (int i = 0; i < 9; ++i) {
y = u * nPixPerVolt;
MoveToEx(hdc, xMin, y, NULL);
LineTo(hdc, xMax, y);
TextOut(hdc, xMin-40, y+8, yMark[i], strlen(yMark[i]));
u += uGridStep;
}
int
int
int
for

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

24 16 777 216 .

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 );

True Color (24 32 ).


256 
. 256 ,
. 
, 
.
256 PALETTEENTRY:


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

0x00, 0x00, 0x00


0x80, 0x00, 0x00
0x00, 0x80, 0x00
0x80, 0x80, 0x00
0x00, 0x00, 0x80
0x80, 0x00, 0x80
0x00, 0x80, 0x80
0xC0, 0xC0, 0xC0
0xC0, 0xDC, 0xC0
0xA6, 0xCA, 0xF0
0xFF, 0xFB, 0xF0
0xA0, 0xA0, 0xA4
0x80, 0x80, 0x80
0xFF, 0x00, 0x00
0x00, 0xFF, 0x00
0xFF, 0xFF, 0x00
0x00, 0x00, 0xFF
0xFF, 0x00, 0xFF
0x00, 0xFF, 0xFF

-
-
-
-
-
-
-

-
-
-

255

0xFF, 0xFF, 0xFF









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 
, .

KWnd.h KWnd.cpp, 1.2.

,
(www.piter.com).

, .

165

. 3.1. 256-

. 3.2. True Color

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.

. 3.3. ( True Color)

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

COLORREF paletteColor[8] = { PALETTERGB(0,31,0), PALETTERGB(0,63,0),


PALETTERGB(0,95,0), PALETTERGB(0,127,0), PALETTERGB(0,159,0),
PALETTERGB(0,191,0), PALETTERGB(0,223,0), PALETTERGB(0,255,0)};

, , ,
.
,
. 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 (65 536)

216 (
High Color). biCompression
BI_RGB, bmiColors
. (WORD)
aBitmapBits .
,

.

biCompression BI_BITFIELDS,


,

aBitmapBits
24

224 (16 777 216)

bmiColors

aBitmapBits ,
.
bmiColors
, .

, biClrUsed

32

224 (24 True Color).

224 (16 777 216)

224 (32-
True Color). biCompression
BI_RGB, bmiColors
.
(DWORD) aBitmapBits
.
,
.
.
biCompression BI_BITFIELDS,


,

aBitmapBits5

32 True Color 


, .
biCompression , 
. . 3.5.
biHeight , biCompression
BI_RGB BI_BITFIELDS,
.

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. , ,

API, Windows 3.1. , , 


Windows 95 Windows NT 4.0, 4, 
Windows 98 Windows 2000 5.
Windows 95 Windows NT 4.0 BITMAPV4HEADER,
Windows 98 Windows 2000 BITMAPV5HEADER.
BITMAPINFOHEADER. 4
RGBA1, , 
 ( ICM 1.02). 5
,
, ICM 2.0.
MSDN.

RGBQUAD.
:
typedef struct tagRGBQUAD
BYTE
rgbBlue;
BYTE
rgbGreen;
BYTE
rgbRed;
BYTE
rgbReserved;
} RGBQUAD;

,
. 
.
DIB,
256 . aBitmapBits
. DIB
True Color (Hi Color), , , .

, True Color, .
biClrUsed
. ,
.

aBitmapBits. biHeight
,
, 
.
. 
.
:
bytesPerLine = ((width * bitCount + 31) / 32) * 4;

width , bitCount .
1

RGBA Red, Green, Blue Alpha.

ICM Integrated Color Management API 


, 
.

181

DIB, biCompression BI_RGB,


,
. aBitmapBits 
,
. DIB 
. 
aBitmapBits ,

. 
3.5.

-
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

, [xd, yd, wd, hd],


, 
, , .

, , 
. 3.6. ,
, .

, .
, . 
, 
.
.
(bitmap
stretching mode), .
SetStretchBltMode:
int

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,

while (GetMessage(&msg, NULL, 0, 0))


TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;

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

KWnd.h KWnd.cpp, 1.2.

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.7. YoungHacker.bmp BmpFileViewer

. 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

CreateBitmap(int nWidth, int nHeight, UINT cPlanes,


cBitsPerPel, CONST VOID* lpvBits);
CreateBitmapIndirect(CONST BITMAP* lpbm);
CreateCompatibleBitmap(HDC hdc, int nWidth, int nHeight);

CreateBitmap DDB nWidth,


nHeight, cPlanes, cBitsPerPel,
lpvBits.
cPlanes cBitsPerPel . 
, GDI
cPlanes cBitsPerPel /.
CreateBitmapIndirect , 
BITMAP:
typedef struct tagBITMAP {
LONG
bmType;
// ( 0)
LONG
bmWidth;
//
LONG
bmHeight;
//

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"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

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 ( )

(
)

Win32 API , DDB


DIB.

201

DIB (DIB section) DIB, 


, 
GDI. DIB 
, , ,
Windows . , ,
DIB.
DIB,  , GDI. 
GDI DIB,
HBITMAP. DIB,
DeleteObject, .

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("Draw icon with ROP", 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 HINSTANCE hShell32;
ICONINFO iconInfo;
BITMAP bmp;
HICON hIcon;
HDC hMemDC;
int x = 20, y = 20;
switch (uMsg)
{
case WM_CREATE:
hShell32 = LoadLibrary("Shell32.dll");
SetClassLong(hWnd, GCL_HBRBACKGROUND,
(LONG)CreateSolidBrush (RGB(180,140,200)));
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
hMemDC = CreateCompatibleDC(hDC);
hIcon = (HICON)LoadImage(hShell32, MAKEINTRESOURCE(ICON_ID),
IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
if (!hIcon) {
MessageBox(hWnd, " ", "Error", MB_OK);
break;
}
GetIconInfo(hIcon, &iconInfo);
GetObject(iconInfo.hbmMask, sizeof(bmp), &bmp);
//
SelectObject(hMemDC, iconInfo.hbmMask);
BitBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0, SRCCOPY);
//

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

WMF Windows Metafile Format.

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

 OEM (Original Equipment Manufacturer


Scan Code).

215

:
HWND SetFocus(HWND hWnd) hWnd,
, .

HWND GetFocus() ,
.


, 
,
.

, . , 
, 
. ANSI1.
. 
, .
, , 
,
.
:
  Caps Lock, Num Lock, Scroll Lock 
Insert. ,
. , 
.


Shift, Ctrl Alt.


. 
.

, , ,
, 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

1 IBM ( , Alt Ctrl


)

29

1, Alt ( WM_KEYDOWN WM_KEYUP 0 )

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, 
:


BOOL CreateCaret(HWND hWnd, HBITMAP hBitmap, int nWidth, int nHeight);

,
.
.
, 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;

KWnd.h KWnd.cpp, 1.2 (


1).

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, NULL, 0, cyChar);


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;

KWnd.h, KWnd.cpp, KDocument.h, KDocument.cpp. 


2.2.

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;

WM_VSCROLL, SB_LINEUP, 0);


WM_VSCROLL, SB_LINEDOWN, 0);
WM_HSCROLL, SB_LINELEFT, 0);
WM_HSCROLL, SB_LINERIGHT, 0);
WM_VSCROLL, SB_PAGEUP, 0);
WM_VSCROLL, SB_PAGEDOWN, 0);

case VK_HOME:
status = GetKeyState(VK_CONTROL);

241

if (0x80 & status) SendMessage(hWnd, WM_VSCROLL, SB_TOP, 0);


else
SendMessage(hWnd, WM_HSCROLL, SB_TOP, 0);
break;
case VK_END:
status = GetKeyState(VK_CONTROL);
if (0x80 & status) SendMessage(hWnd, WM_VSCROLL, SB_BOTTOM, 0);
else
SendMessage(hWnd, WM_HSCROLL, SB_BOTTOM, 0);
break;
}
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;
}
//////////////////////////////////////////////////////////////////////

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;
}
//////////////////////////////////////////////////////////////////////

Russia KWnd.h KWnd.cpp, 


Hello2 ( 1.2), Russia. 
Visual Studio ,
. 5.1.

. 5.1. Visual Studio Russia

, Workspace :
ClassView FileView. FileView
, .

246

5. Windows-




:
1. . Visual Studio 
InsertResource. Insert
Resource (. 5.2).

. 5.2. Insert Resource

Icon New.
Script1 IDI_ICON1 
(. 5.3).

. 5.3. Visual Studio

247

.
Graphics , Colors
.  ,

Graphics Colors.
2. . Device 
Standard (3232).
New Device Image. 
, New Icon Image Target device (. 5.4).

. 5.4. New Icon Image

, 
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-

. 5.5. Icon Properties

, 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-

. 5.8. Visual Studio

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));

hInstance NULL, LoadIcon 


. 
. 1.5 (
1). ,
KWnd hIcon wc
LoadIcon(NULL, IDI_APPLICATION).
LoadIcon 
. NULL.
 LoadIcon ,
IDI_WINLOGO.
, LoadIcon 
. 
(16 16). .
LoadImage.
LoadImage :
, , . :
HANDLE LoadImage(HINSTANCE hinst, LPCTSTR lpszName, UINT uType,
int cxDesired, int cyDesired, UINT fuLoad);

. 
hinst NULL fuLoad LR_LOADFROMFILE,
lpszName
LoadIcon.

254

5. Windows-

hinst NULL, fuLoad 


LR_LOADFROMFILE, lpszName OEM1.
OEM winuser.h
: OBM_ , OIC_ OCR_ .
hinst NULL, fuLoad LR_LOADFROMFILE,
lpszName , 
.
, uType, 
IMAGE_BITMAP, IMAGE_CURSOR IMAGE_ICON.
, cxDesired, .
fuLoad LR_DEFAULTSIZE, 
SM_CXICON
SM_CXCURSOR. , LR_DEFAULTSIZE 
, .
, cyDesired, . 
fuLoad LR_DEFAULTSIZE, 
SM_CXICON SM_CXCURSOR.
, LR_DEFAULTSIZE ,
.
, fuLoad, . 
, . 5.1 (
. . MSDN).
5.1. LoadImage

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.

OEM Original Equipment Manufacturers ( ).

255

5.2. Russia (1- )


//////////////////////////////////////////////////////////////////////
// Russia.cpp
#include <windows.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;
//
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).

. 5.10. Russia (1- )

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

SetRect(&rect, 10, 0, 200, 30);


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);
hCursor = LoadCursor(NULL, IDC_CROSS);
SetClassLong(hWnd, GCL_HCURSOR, (LONG)hCursor);
hCursorUp = LoadCursor(hInst, MAKEINTRESOURCE(IDC_UP));
hCursorDown = LoadCursor(hInst, MAKEINTRESOURCE(IDC_DOWN));
break;
case WM_SIZE:
wClient = LOWORD(lParam);
hClient = HIWORD(lParam);
break;
case WM_MOUSEMOVE:
xPos = LOWORD(lParam);
yPos = HIWORD(lParam);
if (yPos < 16)
SetCursor(hCursorUp);
if (yPos > hClient - 16)
SetCursor(hCursorDown);
InvalidateRect(hWnd, &rect, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
sprintf(text, "xPos = %d, yPos = %d\0", xPos, yPos);
DrawText(hDC, text, -1, &rect, DT_LEFT);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////

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 .
,
,
, .
. 
.

. 5.14. Bitmap Properties


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-

. 5.15. RussiaToday.bmp MS Paint

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

Visual Studio 6.0 ProjectSettings Link 


Object/library modules.
2
WAVE 
RusHymn.wav .
: www.piter.com.

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, 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;
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 ."

KWnd.h, KWnd.cpp StringTable.cpp.


StringTable.cpp , 5.5.
5.5. StringTable
//////////////////////////////////////////////////////////////////////
// StringTable.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "resource.h"
char szAppName[] = "StringTable";
int StatusFileMsg(HWND hwnd, int status, char* fileName);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)

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.

. 6.1. Visual Studio 6.0

Windows . 
.

.


, ,
(main menu), .
.
,
. 
, , 
. 
, .
.
.

273

, 
. . 
(hotkey) .


:
 ;
.
 () 
. ,
, .
 .
 , 
.

. ,
Windows , . 
.
Windows . 
, Windows WM_COMMAND, 
. ,
Windows ,
(popup menu). 
. . 6.2 File 
Visual Studio.


. 6.2. File Visual Studio 6.0

, 
, . 
(. 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.5. Menu Item Properties

. 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).

. 6.6. Menu Item Properties Pop-up

279

IDM_ (ID for a menu).


,  ,
Caption &Open, ID IDM_OPEN.

- , ID_. ,
. ,
MenuDemo1 ID_RECTANGLE,
ID_RHOMB, ID_ELLIPSE. 7 DlgDemo2 ,
.
, .


.
,
. , , 
, .
,

i .


i -
1. .
2. 
Menu Item Properties.
3. , (i + 1) ,
:


Pop-up;

. ,
&;

Menu Item Properties;

(i + 1) 
, i i + 1.

4. ,
:


Pop-up;

, &;

280

6.

Menu Item Properties.

5. , 
:


Pop-up;

Separator;

Menu Item Properties.

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
);

//
//
//
//
//

uFlags : MF_BYCOMMAND MF_BYPOSITION, . , uFlags


, , 
lpNewItem. . 6.3.

. ModifyMenu
, MF_STRING.

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

Draw shape , . 6.8.


6.8. Draw shape (1- )

&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, UINT, WPARAM, LPARAM);


//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("MenuDemo1", 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; //
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).

. 6.7. Draw shape

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;

//
//
//
//
//

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

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_RESIZE - 6.1 */

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.

IDR_AC CELERATOR1. resource.h


. 
.
Accel Properties (. 6.10).

. 6.10. Accel Properties

ID .
, 
. ,
&Open... File MenuDemo1,
IDM_OPEN.
Type VirtKey,
Key . 
. 4.3 ( 4).
Key .
.
Modifiers , 
, .
, Ctrl+O &Open...,
Ctrl, Key O (
O ).

301

, Shift, Ctrl Alt. ,


Windows. , F1 , F4, F5
F6 . Tab, Enter, Esc Spacebar, . , Alt+F4 , Alt+Tab
, Ctrl+Esc .



. .



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;

//
//
//
//
//

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
HACCEL hAccel;
MSG msg;
KWnd mainWnd("MenuDemo3", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
//
hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
while
//
//
if

(GetMessage(&msg, NULL, 0, 0)) {


,

(!TranslateAccelerator(mainWnd.GetHWnd(), hAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);

}
}
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.

. 7.3. Dialog Properties

ID IDD_ABOUT, Caption About


DlgDemo1.
Font , ,
, (MS Sans Serif, 
8).
. Styles, , 
Popup Dialog Frame,
Title bar System menu.
.
. 
 , 
, OK.
. 
Cancel. ,
Delete.

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).

IDC_ (ID for a control).


,
, ID_.

312

7.

. 7.6. Picture Properties

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
.

. 7.7. Static Text


. Static Text
.
Static, . 7.7.

313

Static , 
. 
(. 7.8).

. 7.8. Text Properties

Static Text 
IDC_STATIC.
(, 
Caption), . 
.
ID IDC_STATIC_1,
.
Caption ,
Static Text. 
\t () \n ( ).
Caption DlgDemo1.
Styles (. 7.9).

. 7.9. Static Text Styles

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

Copyright: Finesoft Corporation, 2005.

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;

//
//
//
//
//

BOOL CALLBACK AboutDlgProc(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("DlgDemo1", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);

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.

. 7.14. About DlgDemo1

. , , 
, MenuDemo1
MessageBox.
, 
. 
? , 
?..

Win32 API.



. , 
EnableWindow, :
BOOL EnableWindow(
HWND hWnd,
//
BOOL bEnable //
};

321

.
TRUE, . 
FALSE, .
:
 , ;


( Static Text Edit Box).

( 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.

(Button), (push button), 


, 
. ,
3D , . 
, 
WM_COMMAND BN_CLICKED.
Windows . 
, , 
. ,

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) .

. 7.16. Styles Push Button Properties




Default button .

Owner draw ,
. , 
.

Icon Bitmap , 
.

325

Multiline , ,
.

Flat .

Horizontal alignment Vertical alignment 


.

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

Tab control Owner draw

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

return FALSE; // hBtnHelp


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_DRAWITEM:

// ,
// 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.

. 7.18. About DlgDemo2

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

//
//

enum ShapeSize { MAX, MIN };


typedef struct {
int id_shape;
BOOL fRed;
BOOL fGreen;
BOOL fBlue;
int id_bright;
} ShapeData;

//
//
//
//
//

ShapeData shapeData;

//
// ShapeParamDlgProc WndProc

BOOL CALLBACK ShapeParamDlgProc(HWND, UINT, WPARAM, LPARAM);


BOOL CALLBACK AboutDlgProc(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("DlgDemo3", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
while (GetMessage(&msg, NULL, 0, 0))

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

, ,

Owner Draw No.


, , 
:

Fixed

Owner draw.
WM_MEASUREITEM WM_DRAWITEM,

Variable

, Fixed, ,
.
WM_DRAWITEM WM_MEASUREITEM

Has string Owner draw.


, , .

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

szString iIndex. Sort

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

Edit box List box


DlgDemo, , , . 
 . ,

348

7.

. 
:
 ( ..), 20 ;


( 20 );

( 20 );

( 80 ).

, notebook.dat. ,
, , . 7.10.


7.10. List box


:

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.


hBrush hEditInfoAddr hEditInfoBday.


WM_CTLCOLORSTATIC.

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)
.

. 7.30. Styles Combo Box Properties

Combo box List


box. . Type 
:

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.

Combo box IDC_FONT. 


Styles Drop List Sort.
KWndPlut.h, KWndPlut.cpp MyNotebook2.cpp ,
7.5.
7.5. MyNotebook2
//////////////////////////////////////////////////////////////////////
// KWndPlut.h
#include <windows.h>
class KWnd {
/* 1.2 */
};
//====================================================================

Plut plus utilities.

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

Cancel, Try Again, Continue

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

InvalidateRect(hWnd, NULL, TRUE);


break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, textColor);
if (hFont)
DeleteObject(SelectObject(hDC, hFont));
GetClientRect(hWnd, &rcClient);
DrawText(hDC, "Common Dialogs", -1, &rcClient,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////

. 
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

Common Dialogs (. 7.35).


,
, 
.
Monotype Corsiva 36 .
, ,
File. , , , 

.

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.

8.3. Windows Explorer


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

toolbar, status bar, slider, tooltip

ICC_LISTVIEW_CLASSES

list view, Header

ICC_PROGRESS_CLASS

progress bar

ICC_TAB_CLASSES

tab, tooltip

ICC_TREEVIEW_CLASSES

tree view, tooltip

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;

//
//
//
//
//

#define ID_TOOLBAR 201


#define NUM_BUTTONS 11
#define SEPARATOR_WIDTH 10
HWND hwndToolBar;
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;
KWnd mainWnd("ToolBar", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
// "Common Control Library"
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
icc.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&icc);
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;

}
//====================================================================
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

y0 = tbHeight + (rect.bottom - tbHeight) / 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;
}
// - MenuDemo1
//
pt[0].x = (x1 + x2) / 2; pt[0].y = y1;
pt[1].x = x2;
pt[1].y = (y1 + y2) / 2;
pt[2].x = (x1 + x2) / 2; pt[2].y = y2;
pt[3].x = x1;
pt[3].y = (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) :
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.

. 8.8. TBSTYLE_LIST | TBSTYLE_WRAPABLE



,
 
. 
(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);

Tooltip WS_EX_TOPMOST WS_POPUP, 


, CreateWindowEx.
TTS_NOPREFIX, , (&)

.
TTS_ALWAYSTIP, , 
,  .
, Tooltip
(tool). 
( ).
Tooltip
. 
TTM_ADDTOOL, , :
SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO) &ti);

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
. . . . . . . . . .

=
=
=
.

000000C9, lParam = 0012F768


00009C48, lParam = 00135AC0
00009C48, lParam = 0012FA34
. . . . . . . . . . . . . .


(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), 
().
.


(Simple Mode Status Bars), 


.

, .
SB_SIMPLE:
SendMessage(hwndStatusBar, SB_SIMPLE, fMode, 0);

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);

iPart , , rect RECT, 


.


SB_SETTEXT:
SendMessage(hwndStatusBar, SB_SETTEXT, wParam, (LPARAM)szText);

szText C, wParam


.
wParam iPart | uType.
, iPart 
. , iPart 
255.

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.

8.12. Progress bar


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

sprintf(text, " %.0f %%", percentage);


SendMessage(hwndStatusBar, SB_SETTEXT, 0, (LPARAM)text);
SendMessage(hwndProgressBar, PBM_STEPIT, 0, 0);
Sleep(100);
//
if(PeekMessage(&message, hWnd, 0, 0, PM_REMOVE)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
}
SendMessage(hwndStatusBar, SB_SETTEXT, 0, (LPARAM)" 100 %");
MessageBox(hWnd, " .", " ",
MB_OK | MB_ICONINFORMATION);
//
SendMessage(hwndProgressBar, PBM_SETPOS, 0, 0);
SendMessage(hwndStatusBar, SB_SETTEXT, 0, (LPARAM)" Ready");
break;
case IDM_EXIT:
SendMessage(hWnd, WM_DESTROY, 0, 0);
break;
default:
break;
}
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rect);
sprintf(text, "size = %d, DATA_CHUNK = %d, range = %d",
size, DATA_CHUNK, range);
DrawText(hDC, text, -1, &rect, DT_SINGLELINE | DT_CENTER |
DT_VCENTER);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////

:
#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

hwndSlider = CreateWindow(TRACKBAR_CLASS, NULL, WS_CHILD | WS_VISIBLE, x, y,


width, height, hwndParent, NULL, NULL, NULL);

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, .

. 8.12. Slider Styles

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

Page Down (VK_NEXT)



431

TB_THUMBPOSITION


(
TB_THUMBTRACK)

TB_THUMBTRACK

TB_TOP

Home (VK_HOME) () , wMin

TB_BOTTOM

End (VK_END) () , wMax

,
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).

. 8.16. Spin Tab control


.
CreateWindowEx UPDOWN_CLASS. 
CreateUpDownControl,
, 
, .

. Spin
Controls 
.
Spin Properties General ID
. Styles,
. 8.17, .

436

8.

. 8.17. Spin Styles

Orientation .
Vertical, 
Horizontal.
Alignment 
:
Alignment

Unattached

(,
)

Left

(
)

Right

(
)

Styles :

Auto buddy

Set buddy integer


:
.


No thousands

,
,

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

Align text Centered.

Edit Box

IDC_EDIT_BLUE

Spin

IDC_SPIN_RED

Spin

IDC_SPIN_GREEN

Spin

IDC_SPIN_BLUE

Alignment Right. Auto buddy, Set buddy


integer.

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

GetSystemTimeAdjustment (. 10). "


, Intel Celeron CPU 2.0
15,625 .
15,625 . 2 = 31,25 .
,
Windows "
, . "
"
,
. , "
. ,

.
.
:
 "
; "
;
" (
), ;
( ).
, . "
"
.




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

Below normal Above normal , Windows


2000. Idle , "
, .

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.

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,


LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("CreateMyProcess", 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;
STARTUPINFO si;
static PROCESS_INFORMATION pi;
BOOL success;
switch (uMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_CREATE_PROCESS:
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
success = CreateProcess( NULL, "calc.exe", NULL, NULL, FALSE,
0, NULL, NULL, &si, &pi);
if (!success)
MessageBox(hWnd, "Error of CreateProcess", NULL, MB_OK);
break;
default:
break;
}
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////

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;
}
//////////////////////////////////////////////////////////////////////

ThreadManager, tm_A, tm_B


tm_C .

CreateThread.
WM_CREATE "
hThreadA, hThreadB hThreadC.
ThreadFuncA, ThreadFuncB, ThreadFuncC
. count, "
for. : 100 000 000,
50 000 000 20 000 .
UM_THREAD_DONE.
UM_THREAD_DONE, WndProc
.
. 9.2 CreateMyThreads.

. 9.2. CreateMyThreads

( : A,
B, C), C, B "
A.
.

CreateThread. . "
, C/C++
CreateThread.

456

9.

_beginthreadex Visual C++.


_beginthreadex , CreateThread,
.
CreateThread _beginthreadex, "
typedef
typedef unsigned (__stdcall *PTHREAD_START) (void*)

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
//
);

bManualReset ". TRUE "


, FALSE .
bInitialState
(TRUE) (FALSE).
pszName C",
. pszName NULL, .
, CreateEvent A "
EventName:
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, "EventName");

. "
, .
, . , 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 , "

BOOL ResetEvent(HANDLE 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)
. "
.

(Dynamic Data Exchange, DDE),


"
. DDE , Microsoft "
OLE, ActiveX,
.

(Remote Procedure Call, RPC), ,


IPC. , , "
IPC. RPC "
, .

ActiveX , "
. Microsoft
IDataObject.
Distibuted Component Object Model (DCOM),
ActiveX RPC.

(pipes) . "
, , "

470

9.

. (anonymous
pipes) (named pipes). "
. , "
WinNT/2000,
.
.


(sockets) ,
.
. , "
, "
. Windows API "
.

(mailslots) IPC. "


, , "
, ,
. "
"
, , ,
.

Microsoft Message Queue (MSMQ) "


.
IPC, , "
, , , "
. MSMQ
,
.

: ) (
); ) WM_COPYDATA.
Win32.


.


. 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
.


Memory Mapped File API , ,


. , Windows
.

472


9.

Heap Memory API , "


().

,

. "
, ,
. .
:
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;

dwData 32" , "


".

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

. , "
, .


" hEvtServIsFree hEvtServIsDone.

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

HANDLE hEvtRecToServ; // " "


HANDLE hEvtServIsFree; // " "
HANDLE hEvtServIsDone; // " "
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("ClientApp", hInstance, nCmdShow, WndProc,
MAKEINTRESOURCE(IDR_MENU1), 100, 100, 450, 150);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

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.

. 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

,
.
, "
:
 , "
.


Windows Explorer "


. , "
.

" .
, ,
.

, ,
. " " "

.
, 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

16 Windows. Windows


32 ,
, Windows 49,7 .
Windows 
, Windows ,
. ,
Windows ,
, .
Windows ,
( , 
MSDOS).
10 15
. , 
,
GetSystemTimeAdjustment, :
BOOL GetSystemTimeAdjustment(PDWORD lpTimeAdjustment,PDWORD lpTimeIncrement,
PBOOL lpTimeAdjustmentDisabled);

, 
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

, , , , Intel Celeron, AMD, VIA . .

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;

Visual Studio 6.0 ProjectSettings, Link,


Object/library modules.


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.

10.3. , uDelay KTimer


U_SEC,

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.

Celeron CPU 2,0 Microsoft Windows 2000 (


15,625 ). 
WM_TIMER 
.
10.5.
10.5. SetTimer1Test
//////////////////////////////////////////////////////////////////////
// SetTimer1Test.cpp
#include <windows.h>
#include <stdio.h>
#include "KWnd.h"
#include "KTimer.h"
KTimer timer;
#define ID_TIMER 1
#define TIME_PERIOD 1
#define N 1000
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("SetTimer1 - test", 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;
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;

InvalidateRect(hWnd, NULL, TRUE);

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

Visual Studio 6. ProjectSettings,


Link Object/library modules winmm.lib.

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

mmResult = timeSetEvent(TIME_PERIOD, 0, TimeProc, reinterpret_cast<DWORD>(hWnd),


TIME_PERIODIC);
if (!mmResult)
MessageBox(hWnd, " ", "Error", MB_OK);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
// min max
minT = maxT = amount = realTimeInterval[i0];
for (i = i0 + 1; i < N; ++i) {
if (realTimeInterval[i] < minT)
minT = realTimeInterval[i];
if (realTimeInterval[i] > maxT)
maxT = realTimeInterval[i];
amount += realTimeInterval[i];
}
sprintf(text, "minT = %.3f, maxT = %.3f, average = %.3f\0",
minT, maxT, amount / (N - i0));
TextOut(hDC, 10, 10, text, strlen(text));
EndPaint(hWnd, &ps);
break;
case UM_READY:
MessageBox(hWnd, "", " ", MB_OK);
SendMessage(hWnd, WM_DESTROY, 0, 0);
break;
case WM_DESTROY:
timeKillEvent(mmResult);
//timeEndPeriod(1);
// #2
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//====================================================================
void CALLBACK TimeProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)

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,

maxT = 100.62, average = 100.00.

, , 
.
Windows , 
.
.
, ,
TimeProc .
,
TIME_PERIOD, TimeProc
, .
, , 
? 
, , ,
. 
.

515

11

DLL

(dynamic link libraries (DLL))


, ,
, . ,
DLL ,
.
, DLL ,
.
, , DLL.
DLL 
.
(, , ), .
DLL ( DLL,
) DLL kernel32.dll, user32.dll, gdi32.dll
. Visual Studio,
.
DLL, ,
. , , 8,
comctl32.dll,
.
DLL
.
DLL :
 . DLL
, ,
, , . ,
,
DLL .
 .
, . DLL
, .
 . DLL ,
,
. , 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

Component Object Model (COM)


.

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.
,
.

#define EXPORT extern "C" __declspec(dllexport)

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;
}
//////////////////////////////////////////////////////////////////////

Win32 Application MyLib.h


ImplClient.cpp.
MyLib.lib,
.
.
Project Settings
Project Settings Link. :
 Category General;
 Object/library modules MyLib.lib;
 OK.
(F7).
EXE ,
DLL .
Visual Studio, MyLib.dll Debug.
.
, . 11.1 .
OK, , (. 11.1 ).
, ,
( Print), MyLib.dll.

DLL

521

. 11.1. Print MyLib.dll

, Visual Studio,
? ,
, Output. F10
.
,
F10. (
) Output :
Loaded
Loaded
Loaded
Loaded
Loaded

'C:\WINNT\system32\ntdll.dll', no matching symbolic information found.


symbols for 'F:\ProgWinApi\ImplClient\Debug\MyLib.dll'
'C:\WINNT\system32\user32.dll', no matching symbolic information found.
'C:\WINNT\system32\kernel32.dll', no matching symbolic information found.
'C:\WINNT\system32\GDI32.DLL', no matching symbolic information found.

, , 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

Win32 Application ExplClient.cpp.


, MyLib.h
, , .
.
.
MyLib.dll EXE .
Visual Studio, MyLib.dll
Debug. ,
ImplClient.exe.

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;
}
//////////////////////////////////////////////////////////////////////

Win32 Application MyLib.h


DelayLoadClient.cpp. MyLib.lib.
:
MyLib.lib delayimp.lib. , ProjectSettingsLinkObject/
library modules. , Link, Project Options
/delayload:MyLib.dll.
Debug MyLib.dll
EXE . ,
ImplClient (. . 11.1).

. F10 .
, ,
Output :
Loaded 'C:\WINNT\system32\ntdll.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\kernel32.dll', no matching symbolic information found.

, 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

The experiment was a success!

IDS_3

By!

4. C (FileSave As) MyResEng.rc.


5. MyResEng.rc
resource.h MyResEng.h.

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
, :


BOOL APIENTRY DllMain( HANDLE hModule, DWORD dwReason, LPVOID lpReserved)


{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
// (, )
// , FALSE;
return TRUE;
case DLL_THREAD_ATTACH:
// ,
break;
case DLL_THREAD_DETACH:

(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

n TLS TLS_MINIMUM_AVAILABLE. Windows 95/NT 64, , Win


dows 2000, 1088.
, TlsAlloc
, n .
free in_use, , TLS.
free, TlsAlloc in_use
.
TLS .
.
.
, TlsSetValue,
gdwTlsIndex:
TlsSetValue(gdwTlsIndex, pGlobData);

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

void Print(LPCTSTR text);

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;
}
//////////////////////////////////////////////////////////////////////

Win32 Application MtTlsClient


MtTlsClient.cpp MyMtLib.h.
MyMtLib.lib.
MyMtLib.lib. Debug
MyMtLib.dll (F5).
, . 11.3.
OK , ,
Print
.
Output.
:
Loaded symbols for 'F:\ProgWinApi\MtTlsClient\Debug\MyMtLib.dll'
...
DllMain: DLL, hinstDLL = 10000000
DllMain: gdwTlsIndex = 3
DllMain: , threadID = 8E0
DllMain: 143778
DllMain: 143778 3
Print: 8E0, text = ' : !'

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

KWnd.h KWnd.cpp, 1.2.


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

stone.bmp Styles, C:\Program


Files\Microsoft Office\Office 10\Bitmaps\Styles.

Ball.bmp BounceBall, 
, www.piter.com.

DIB

543

Stone.bmp IDB_STONE, Ball.bmp


IDB_BALL.
BounceBall.rc resource.h.
,
BounceBall , . 12.1.

. 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 .

ARINC Aeronautical Radio, INC. (USA).

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"

#define ID_STATUSBAR 201


#define PACK_PERIOD

//

#define LEFT_MARGIN -683 // angle = -60/


#define RIGHT_MARGIN 683 // angle = +60/
#define Pi 3.141592653589793
HDC g_hDC;
HWND hwndStatusBar;
double sweepSpeedDue; // ( )
double speedWithPackPeriod; // PACK_PERIOD
int sieveCoeff;
// /
double sweepTimeDue; // ()
double sweepTimeFact; // ()
int scanAngle;
//
double digitWeight; // scanAngle
COLORREF cell[512]; //
int X0, Y0;
//
double x, y;
//
KTimer timer;
typedef enum { FORTH, BACK } DIR;
DIR direction = FORTH;
//
void
void
void
void
void

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();

sweepTimeFact = timer.GetTime() / 1000;


timer.Start();
sprintf(text, " : %.2f ",
sweepTimeFact);
SendMessage(hwndStatusBar, SB_SETTEXT, 3, (LPARAM)text);
}
if (direction == BACK)
if (--scanAngle <= LEFT_MARGIN) {
direction = FORTH;
SetColorBeamForth();
}
}
//====================================================================
void SetColorBeamForth() {
for (int i = 0; i < 512; ++i) {

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);

inline void Draw(HDC hdc) {


StretchDIBits(hdc, 0, 0, width, height,
0, 0, width, height, pBits, &bmi,
DIB_RGB_COLORS, SRCCOPY);
}
private:
HBITMAP hBmp;
BITMAPINFO
bmi;
int width;
int height;
int
bytePerLine;
PVOID pBits;
};

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

1. Visual C++ 6.0

Visual C++
Microsoft Developer Studio, , 
Visual C++, Visual J, MS Fortran Power Station
.

. 1.1. ( ) Visual C++

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.

New Project Information 


, 
. OK.
,
. 1.2.


. 1.2. Visual C++ HelloFromMsgBox


1

, D:\MyProjects.

566

1. Visual C++ 6.0

, 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.


HelloFromMsgBox files Project Workspace 


Source Files.

Add Files to Folder

IDE.


567

Insert Files into Project


(HelloFromMsgBox.cpp) OK.


:
 FileNew. 
New.


Files ( C++ Source File).

File Name ( HelloFrom


MsgBox.cpp). Add to project .

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

1. Visual C++ 6.0

#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;
}

. 1.3 Visual C++ .



. Developer Studio
. 
, .
.
/
Header Files Project Workspace.
Add Files to Folder.
Insert Files into Project .
, , AnyName.h, OK.

Source Files Header Files, Project Workspace,


.
. , ,
Project Workspace .

,
Build ,
.
Build:
 Compile . 
Output.


Build . , 
. 
, , 
.
Output. , 
.exe .

Rebuild All , Build, 


, .

Execute , 
.
Compile, Build Execute 
Build MiniBar .
Build MiniBar . 1.4.


IDE.

569

Build
, .
Rebuid All.
.

. 1.4. Build MiniBar

, 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

1. Visual C++ 6.0

ProjectName.dsw. ,

2. Visual C++. File


Recent Workspaces. 
, , ProjectName.dsw,
.
3. , 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

1. Visual C++ 6.0

.
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

1. Visual C++ 6.0

. 
. 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.

. 1.6. Find in Files

, 
.
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

1. Visual C++ 6.0


(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
, 
.

. 2.1. ( ) Visual Studio.NET

578

2. VisualStudio.NET

, Visual Studio 6.0.


Project Workspace 
. Solution Explorer.
Editor ,
StartPage.
.
, , 
. 
, .
Output  
, .


Win32 Application empty project 
. 
FileNewProject. New Project, 
. 2.2.

. 2.2. New Project

Project Types Visual C++ Project. New Project


, . 2.3.
Visual C++ Project Win32.
New Project , . 2.4.
Templates Win32 Project.
Name, , HelloFromMsgBox.
Location, , E:\MyProject. 
OK Win32 Application Wizard HelloFromMsgBox
(. 2.5).

579

. 2.3. New Project Visual C++ Project

. 2.4. New Project Win32

. 2.5. Win32 Application Wizard HelloFromMsgBox

Application Settings. , 
. 2.6.
Additional options Empty project 
Finish. Visual Studio.NET , . 2.7.

580

2. VisualStudio.NET

. 2.6. Application Settings

. 2.7. Visual Studio.NET

.
HelloFromMsgBox, ,
. . HelloFromMsgBox.sln
( ), HelloFromMsgBox.vcproj .
, .sln .dsw Visual
C++ 6.0 , , .vcproj .dsp.


, 
.

581

Source Files Solution Explorer.


AddAdd New Item. Add New
Item (. 2.8).

. 2.8. Add New Item

Templates C++ File Header File


, .
Name, , HelloFromMsgBox, Open.
Source Files Solution Explorer 
, , HelloFromMsgBox.cpp, 
.

. 2.9. Visual Studio.NET HelloFromMsgBox.cpp

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.

. 2.10. Visual Studio.NET HelloFromMsgBox


.

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++

. 3.2. Message Options

Selected Object :
(Window);

(Text);

(Thread ID);

(Process ID).
OK, Messages (Window)
(. 3.3).


. 3.3. Messages (Window)

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++

atomic access 459

page file 471


page space 67
palette 59
pen 59
physical device space 67
primary thread 443
Progress bar 423
project workspace 563

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

scan code 214


SDK 19
security descriptor 442
semaphore 466
shortcut menu 293
Slider 428
sockets 470
Spin 435
status bar 413
swap file 471

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