Drawing Dots and Lines
x(t) = (1 - t)3 x0 + 3t (1 - t)2 x1 + 3t2 (1 - t) x2 + t3 x3
y(t) = (1 - t)3 y0 + 3t (1 - t)2 y1 + 3t2 (1 - t) y2 + t3 y3
Drawing Filled Areas
Alternate and Winding modes
At first, the difference between alternate and winding modes seems rather simple. For alternate mode, you can imagine a line drawn from a point in an enclosed area to infinity. The enclosed area is filled only if that imaginary line crosses an odd number of boundary lines. This is why the points of the star are filled but the center is not.
The example of the five-pointed star makes winding mode seem simpler than it actually is. When you're drawing a single polygon, in most cases winding mode will cause all enclosed areas to be filled. But there are exceptions.
To determine whether an enclosed area is filled in winding mode, you again imagine a line drawn from a point in that area to infinity. If the imaginary line crosses an odd number of boundary lines, the area is filled, just as in alternate mode. If the imaginary line crosses an even number of boundary lines, the area can either be filled or not filled. The area is filled if the number of boundary lines going in one direction (relative to the imaginary line) is not equal to the number of boundary lines going in the other direction.
viewport & window
The GDI Mapping Mode
The viewport is specified in terms of device coordinates (pixels). Most often the viewport is the same as the client area, but it can also refer to whole-window coordinates or screen coordinates if you've obtained a device context from GetWindowDC or CreateDC . The point (0, 0) is the upper left corner of the client area (or the whole window or the screen). Values of x increase to the right, and values of y increase going down.
The window is specified in terms of logical coordinates, which might be pixels, millimeters, inches, or any other unit you want. You specify logical window coordinates in the GDI drawing functions.
keystroke
The
six keystroke-message fields of the lParam variable:
31
30
29
28 27 26 25 24 23 ... 16
15 ... 00
31 : Transition State
30 :
Previous Key State
29 : Context Code
24 : Extended Key Flag
16
- 23 : 8-Bit OEM Scan Code
00 - 15 : 16-Bit Repeat Count
WM_TIMER
void
RotatePoint (POINT pt[], int iNum, int iAngle)
{
int i ;
POINT ptTemp ;
for (i = 0 ; i < iNum ; i++)
{
ptTemp.x = (int) (pt[i].x * cos (TWOPI * iAngle / 360) +
pt[i].y * sin (TWOPI * iAngle / 360)) ;
ptTemp.y = (int) (pt[i].y * cos (TWOPI * iAngle / 360) -
pt[i].x * sin (TWOPI * iAngle / 360)) ;
pt[i] = ptTemp ;
}
}
Using the Timer for a Clock
x' = x * cos (a) + y * sin (a)
y' = y * cos (a) - x * sin (a)
CreateIC
// Invert the rectangle if the button is
selected
if (pdis->itemState & ODS_SELECTED)
InvertRect (pdis->hDC, &pdis->rcItem) ;
Resource
Icons,
Cursors, Strings, and Custom ResourceshIcon = LoadIcon (hInstance,
MAKEINTRESOURCE (125)) ;
The obscure method is this:
hIcon =
LoadIcon (hInstance, TEXT ("#125")) ;
Windows recognizes the initial
# character as prefacing a number in ASCII form.
ID numbers you use
to add commands to the system menu
must be lower than 0xF000
MapDialogRect
wndclass.cbWndExtra = DLGWINDOWEXTRA ; // Note!
Clipboard
GMEM_MOVEABLE
flag
allows Windows to move a memory block in virtual memory. This
doesn't necessarily mean that the memory block will be moved in physical
memory,
but the address that the application uses to read and write to the block
can
change. Like the relation between Handle & Pointer
OpenClipboard
(hwnd) ;
EmptyClipboard () ;
SetClipboardData (CF_TEXT,
hGlobalText) ;
SetClipboardData (CF_BITMAP, hBitmap) ;
SetClipboardData
(CF_METAFILEPICT, hGlobalMFP) ;
CloseClipboard () ;
Delayed
Rendering
After
you call SetClipboardData
, don't continue to use the memory
block. It no longer belongs to your program, and you should treat the
handle as invalid.
Delayed Rendering
OpenClipboard
(hwnd) ;
EmptyClipboard
() ;
SetClipboardData
(iFormat,
NULL) ;
CloseClipboard
() ;
WM_RENDERFORMAT
, WM_RENDERALLFORMATS
( used when
terminate), and WM_DESTROYCLIPBOARD
case WM_RENDERALLFORMATS :
OpenClipboard (hwnd) ;
EmptyClipboard () ;
// fall through
case WM_RENDERFORMAT :
[put text into global
memory block]
SetClipboardData
(CF_TEXT, hGlobal) ;
if (message ==
WM_RENDERALLFORMATS)
CloseClipboard () ;
return 0
;
delayed
rendering must process three messages in its window procedure:
WM_RENDERFORMAT, WM_RENDERALLFORMATS, and WM_DESTROYCLIPBOARD. Windows
sends your window procedure a WM_RENDERFORMAT message when another
program calls GetClipboardData
. The value of wParam
is the
format requested. When you process the WM_RENDERFORMAT message, don't
open and empty the clipboard. Simply create a global memory block for
the format given by wParam
, transfer the data to it, and call SetClipboardData
with the correct format and the global handle. Obviously, you'll need
to retain information in your program to construct this data properly
when processing WM_RENDERFORMAT. When another program calls EmptyClipboard
,
Windows sends your program a WM_DESTROYCLIPBOARD message. This tells
you that the information to construct the clipboard data is no longer
needed. You are no longer the clipboard owner. WM_RENDERALLFORMATS
message is one of the last messages your window procedure receives
Private
Data Formats
The easiest involves data that is ostensibly in one
of the standard clipboard formats (that is, text, bitmap, or metafile)
The
second way to use private formats involves the CF_OWNERDISPLAY flag.
The
third way to use private clipboard data formats is to register your own
clipboard format name.
WM_DRAWCLIPBOARD
and WM_PAINTCLIPBOARD
messages. The WM_PAINTCLIPBOARD message is sent by a clipboard viewer
to programs that use the CF_OWNERDISPLAY clipboard format. The WM_
DRAWCLIPBOARD message is sent by Windows to the current clipboard viewer
ChangeClipboardChain
(hwnd, hwndNextViewer) ;
PATPAINT
The PATPAINT raster
operation involves a more complex operation. The result is equal to a
bitwise OR operation between the pattern, the destination, and the
inverse of the source.
The 15 ROP codes that have names are shown
here.
Pattern (P): | 1 1 1 1 0 0 0 0 | |||
Source (S): | 1 1 0 0 1 1 0 0 | |||
Destination (D): | 1 0 1 0 1 0 1 0 | Boolean Operation | ROP Code | Name |
Result: | 0 0 0 0 0 0 0 0 | 0 | 0x000042 | BLACKNESS |
0 0 0 1 0 0 0 1 | ~ (S ¦ D) | 0x1100A6 | NOTSRCERASE | |
0 0 1 1 0 0 1 1 | ~S | 0x330008 | NOTSRCCOPY | |
0 1 0 0 0 1 0 0 | S & ~D | 0x440328 | SRCERASE | |
0 1 0 1 0 1 0 1 | ~D | 0x550009 | DSTINVERT | |
0 1 0 1 1 0 1 0 | P ^ D | 0x5A0049 | PATINVERT | |
0 1 1 0 0 1 1 0 | S ^ D | 0x660046 | SRCINVERT | |
1 0 0 0 1 0 0 0 | S & D | 0x8800C6 | SRCAND | |
1 0 1 1 1 0 1 1 | ~S ¦ D | 0xBB0226 | MERGEPAINT | |
1 1 0 0 0 0 0 0 | P & S | 0xC000CA | MERGECOPY | |
1 1 0 0 1 1 0 0 | S | 0xCC0020 | SRCCOPY | |
1 1 1 0 1 1 1 0 | S ¦ D | 0xEE0086 | SRCPAINT | |
1 1 1 1 0 0 0 0 | P | 0xF00021 | PATCOPY | |
1 1 1 1 1 0 1 1 | P ¦ ~S ¦ D | 0xFB0A09 | PATPAINT | |
1 1 1 1 1 1 1 1 | 1 | 0xFF0062 | WHITENESS |
PatBlt
Besides
BitBlt
and StretchBlt
, Windows also includes a function
called PatBlt
("pattern block transfer"). This is the simplest of
the three "blt" functions. Unlike BitBlt
and StretchBlt
,
it uses only a destination device context.
Pattern (P): | 1 1 0 0 | |||
Destination (D): | 1 0 1 0 | Boolean Operation | ROP Code | Name |
Result: | 0 0 0 0 | 0 | 0x000042 | BLACKNESS |
0 0 0 1 | ~(P ¦ D) | 0x0500A9 | ||
0 0 1 0 | ~P & D | 0x0A0329 | ||
0 0 1 1 | ~P | 0x0F0001 | ||
0 1 0 0 | P & ~D | 0x500325 | ||
0 1 0 1 | ~D | 0x550009 | DSTINVERT | |
0 1 1 0 | P ^ D | 0x5A0049 | PATINVERT | |
0 1 1 1 | ~(P & D) | 0x5F00E9 | ||
1 0 0 0 | P & D | 0xA000C9 | ||
1 0 0 1 | ~(P ^ D) | 0xA50065 | ||
1 0 1 0 | D | 0xAA0029 | ||
1 0 1 1 | ~P ¦ D | 0xAF0229 | ||
1 1 0 0 | P | 0xF00021 | PATCOPY | |
1 1 0 1 | P ¦ ~D | 0xF50225 | ||
1 1 1 0 | P ¦ D | 0xFA0089 | ||
1 1 1 1 | 1 | 0xFF0062 | WHITENESS |
DDB
iWidthBytes
= (cx * cBitsPixel + 15) & ~15) >> 3 ;