/*----------------------------------------
BTNLOOK.C -- Button Look Program
(c) Charles Petzold, 1998
----------------------------------------*/
#include
struct
{
int iStyle ;
TCHAR * szText ;
}
button[] =
{
BS_PUSHBUTTON, TEXT ("PUSHBUTTON"),
BS_DEFPUSHBUTTON, TEXT ("DEFPUSHBUTTON"),
BS_CHECKBOX, TEXT ("CHECKBOX"),
BS_AUTOCHECKBOX, TEXT ("AUTOCHECKBOX"),
BS_RADIOBUTTON, TEXT ("RADIOBUTTON"),
BS_3STATE, TEXT ("3STATE"),
BS_AUTO3STATE, TEXT ("AUTO3STATE"),
BS_GROUPBOX, TEXT ("GROUPBOX"),
BS_AUTORADIOBUTTON, TEXT ("AUTORADIO"),
BS_OWNERDRAW, TEXT ("OWNERDRAW")
} ;
#define NUM (sizeof button / sizeof button[0])
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("BtnLook") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Button Look"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndButton[NUM] ;
static RECT rect ;
static TCHAR szTop[] = TEXT ("message wParam lParam"),
szUnd[] = TEXT ("_______ ______ ______"),
szFormat[] = TEXT ("%-16s%04X-%04X %04X-%04X"),
szBuffer[50] ;
static int cxChar, cyChar ;
HDC hdc ;
PAINTSTRUCT ps ;
int i ;
switch (message)
{
case WM_CREATE :
cxChar = LOWORD (GetDialogBaseUnits ()) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;
for (i = 0 ; i < NUM ; i++)
hwndButton[i] = CreateWindow ( TEXT("button"),
button[i].szText,
WS_CHILD | WS_VISIBLE | button[i].iStyle,
cxChar, cyChar * (1 + 2 * i),
20 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU) i,
((LPCREATESTRUCT) lParam)->hInstance, NULL) ;
return 0 ;
case WM_SIZE :
rect.left = 24 * cxChar ;
rect.top = 2 * cyChar ;
rect.right = LOWORD (lParam) ;
rect.bottom = HIWORD (lParam) ;
return 0 ;
case WM_PAINT :
InvalidateRect (hwnd, &rect, TRUE) ;
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
SetBkMode (hdc, TRANSPARENT) ;
TextOut (hdc, 24 * cxChar, cyChar, szTop, lstrlen (szTop)) ;
TextOut (hdc, 24 * cxChar, cyChar, szUnd, lstrlen (szUnd)) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DRAWITEM :
case WM_COMMAND :
ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ;
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
TextOut (hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1),
szBuffer,
wsprintf (szBuffer, szFormat,
message == WM_DRAWITEM ? TEXT ("WM_DRAWITEM") :
TEXT ("WM_COMMAND"),
HIWORD (wParam), LOWORD (wParam),
HIWORD (lParam), LOWORD (lParam))) ;
ReleaseDC (hwnd, hdc) ;
ValidateRect (hwnd, &rect) ;
break ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
所有按钮窗口样式都以字母「BS」开头,它表示「按钮样式」
CreateWindow调用使用下面这些参数:
TEXT ("button")
button[i].szText
WS_CHILD | WS_VISIBLE |button[i].iStyle
cxChar
cyChar * (1 + 2 * i)
20 * xChar
7 * yChar / 4
(HMENU) i
((LPCREATESTRUCT) lParam) ->hInstance NULL
用鼠标单击按钮时,子窗口控件就向其父窗口发送一个WM_COMMAND消息。BTNLOOK拦截WM_COMMAND消息并显示wParam和lParam的值,它们的含义如下:
父窗口可以向子窗口发送以前缀WM开头的许多消息,也可以发送前缀BM表示的按钮消息。
每个子窗口控件都具有一个在其兄弟中唯一的窗口句柄和ID值。对于句柄和ID这两者,知道其中的一个您就可以获得另一个。如果您知道子窗口控件的窗口句柄,那么您可以用下面的叙述来获得ID:
id = GetWindowLong (hwndChild, GWL_ID) ;
前面鼠标例子中的CHECKER3程序曾用此函数(与SetWindowLong一起)来维护注册窗口类别时保留的特殊区域的数据。在建立子窗口时,Windows保留了GWL_ID标识符存取的数据。
您也可以使用:
id = GetDlgCtrlID (hwndChild) ;
虽然函数中的「Dlg」部分指的是对话框,但实际上这是一个通用的函数。知道ID和父窗口句柄,您就能获得子窗口句柄:
hwndChild = GetDlgItem (hwndParent, id) ;
仿真按钮闪动
SendMessage (hwndButton, BM_SETSTATE, 1, 0) ;
SendMessage (hwndButton, BM_SETSTATE, 0, 0) ; // 恢复正常
初始化带勾选标记的BS_CHECKBOX
SendMessage (hwndButton, BM_SETCHECK, 1, 0) ;
获取按钮状态
iCheck = (int) SendMessage (hwndButton, BM_GETCHECK, 0, 0) ;
如果该按钮被选中,则iCheck的值为TRUE或者非零数;如果按钮末被选中,则iCheck的值为FALSE或0。
当您收到来自单选按钮的WM_COMMAND消息时,应该向它发送wParam等于1的BM_SETCHECK消息来显示其选中状态:
SendMessage (hwndButton, BM_SETCHECK, 1, 0) ;
对同组中的其它所有单选按钮,您可以通过向它们发送wParam等于0的BM_SETCHECK消息来显示其未选中状态:
SendMessage (hwndButton, BM_SETCHECK, 0, 0) ;
SetWindowText (hwnd, pszString) ; // 改变文字
// 获得文字
iLength = GetWindowText (hwnd, pszBuffer, iMaxLength) ;
iMaxLength指定复制到pszBuffer指向的缓冲区中的最大字符数。该函数传回复制的字符数。您可以首先通过下面的呼叫来获得特定文字的长度:
iLength = GetWindowTextLength (hwnd) ;
// 没有将WS_VISIBLE包含在窗口类别中,就这样显示
ShowWindow (hwndChild, SW_SHOWNORMAL);
ShowWindow (hwndChild, SW_HIDE) ; // 隐藏
IsWindowVisible (hwndChild) ; // 获取状态
EnableWindow (hwndChild, FALSE) ; // 禁用
EnableWindow (hwndChild, TRUE) ; // 启用
IsWindowEnabled (hwndChild) ; // 启用状态
父窗口可以阻止子窗口控件获得输入焦点。
case WM_KILLFOCUS :
if (hwnd == GetParent ((HWND) wParam))
SetFocus (hwnd) ;
return 0 ;
使用SetTextColor和SetBkColor将文字和文字背景的颜色改变为系统颜色
SetBkColor (hdc, GetSysColor (COLOR_BTNFACE)) ;
SetTextColor (hdc, GetSysColor (COLOR_WINDOWTEXT)) ;
这样显示区域背景、文字背景和文字的颜色都与按钮的颜色一致了。但是,如果当您的程序执行时,使用者改变了系统颜色,您可能要改变文字背景颜色和文字颜色。这时您可以使用下面的程序代码:
case WM_SYSCOLORCHANGE:
InvalidateRect (hwnd, NULL, TRUE) ;
break ;
当子窗口即将为其显示区域着色时,由按钮控件发送给其父窗口消息处理程序的一个消息:WM_CTLCOLORBTN消息。父窗口可以利用这个机会来改变子窗口消息处理程序将用来着色的颜色。
当父窗口消息处理程序收到WM_CTLCOLORBTN消息时,wParam消息参数是按钮的设备内容句柄,lParam是按钮的窗口句柄。当父窗口消息处理程序得到这个消息时,按钮控件已经获得了它的设备内容。当您的窗口消息处理程序处理一个WM_CTLCOLORBTN消息
时,您必须完成以下三个动作:
/*------------------------------------------------------------------------
OWNDRAW.C -- Owner-Draw Button Demo Program
(c) Charles Petzold, 1996
-------------------------------------------------------------------------*/
#include
#define ID_SMALLER 1
#define ID_LARGER 2
#define BTN_WIDTH ( 8 * cxChar)
#define BTN_HEIGHT ( 4 * cyChar)
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE hInst;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("OwnDraw");
MSG msg;
HWND hwnd;
WNDCLASS wndclass;
hInst = hInstance;
wndclass.style = CS_HREDRAW |
CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL,
IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,
IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject
(WHITE_BRUSH);
wndclass.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Owner-Draw Button Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void Triangle(HDC hdc, POINT pt[])
{
SelectObject(hdc, GetStockObject(BLACK_BRUSH));
Polygon(hdc, pt, 3);
SelectObject(hdc, GetStockObject(WHITE_BRUSH));
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM
wParam, LPARAM lParam)
{
static HWND hwndSmaller, hwndLarger;
static int cxClient, cyClient, cxChar,
cyChar;
int cx, cy;
LPDRAWITEMSTRUCT pdis;
POINT pt[3];
RECT rc;
switch (message)
{
case WM_CREATE:
cxChar = LOWORD(GetDialogBaseUnits());
cyChar = HIWORD(GetDialogBaseUnits());
// Create the owner-draw pushbuttons
hwndSmaller = CreateWindow(TEXT("button"), TEXT(""),
WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
0, 0, BTN_WIDTH, BTN_HEIGHT,
hwnd, (HMENU)ID_SMALLER, hInst, NULL);
hwndLarger = CreateWindow(TEXT("button"), TEXT(""),
WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
0, 0, BTN_WIDTH, BTN_HEIGHT,
hwnd, (HMENU)ID_LARGER, hInst, NULL);
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
// Move the buttons to the new center
MoveWindow(hwndSmaller, cxClient / 2 - 3 *
BTN_WIDTH / 2,
cyClient / 2 - BTN_HEIGHT / 2,
BTN_WIDTH, BTN_HEIGHT, TRUE);
MoveWindow(hwndLarger, cxClient / 2 + BTN_WIDTH /
2, cyClient / 2 - BTN_HEIGHT / 2,
BTN_WIDTH, BTN_HEIGHT,
TRUE);
return 0;
case WM_COMMAND:
GetWindowRect(hwnd, &rc);
// Make the window 10% smaller or larger
switch (wParam)
{
case ID_SMALLER:
rc.left += cxClient / 20;
rc.right -= cxClient / 20;
rc.top += cyClient / 20;
rc.bottom -= cyClient / 20;
break;
case ID_LARGER:
rc.left -= cxClient / 20;
rc.right += cxClient / 20;
rc.top -= cyClient / 20;
rc.bottom += cyClient / 20;
break;
}
MoveWindow(hwnd, rc.left, rc.top, rc.right - rc.left,
rc.bottom - rc.top, TRUE);
return 0;
case WM_DRAWITEM:
pdis = (LPDRAWITEMSTRUCT)lParam;
// Fill area with white and frame it black
FillRect(pdis->hDC, &pdis->rcItem,
(HBRUSH)GetStockObject(WHITE_BRUSH));
FrameRect(pdis->hDC, &pdis->rcItem,
(HBRUSH)GetStockObject
(BLACK_BRUSH));
// Draw inward and outward black triangles
cx = pdis->rcItem.right - pdis->rcItem.left;
cy = pdis->rcItem.bottom - pdis->rcItem.top;
switch (pdis->CtlID)
{
case ID_SMALLER:
pt[0].x = 3 * cx / 8; pt[0].y = 1 * cy / 8;
pt[1].x = 5 * cx / 8; pt[1].y = 1 * cy / 8;
pt[2].x = 4 * cx / 8; pt[2].y = 3 * cy / 8;
Triangle(pdis->hDC, pt);
pt[0].x = 7 * cx / 8; pt[0].y = 3 * cy / 8;
pt[1].x = 7 * cx / 8; pt[1].y = 5 * cy / 8;
pt[2].x = 5 * cx / 8; pt[2].y = 4 * cy / 8;
Triangle(pdis->hDC, pt);
pt[0].x = 5 * cx / 8; pt[0].y = 7 * cy / 8;
pt[1].x = 3 * cx / 8; pt[1].y = 7 * cy / 8;
pt[2].x = 4 * cx / 8; pt[2].y = 5 * cy / 8;
Triangle(pdis->hDC, pt);
pt[0].x = 1 * cx / 8; pt[0].y = 5 * cy / 8;
pt[1].x = 1 * cx / 8; pt[1].y = 3 * cy / 8;
pt[2].x = 3 * cx / 8; pt[2].y = 4 * cy / 8;
Triangle(pdis->hDC, pt);
break;
case ID_LARGER:
pt[0].x = 5 * cx / 8; pt[0].y = 3 * cy / 8;
pt[1].x = 3 * cx / 8; pt[1].y = 3 * cy / 8;
pt[2].x = 4 * cx / 8; pt[2].y = 1 * cy / 8;
Triangle(pdis->hDC, pt);
pt[0].x = 5 * cx / 8; pt[0].y = 5 * cy / 8;
pt[1].x = 5 * cx / 8; pt[1].y = 3 * cy / 8;
pt[2].x = 7 * cx / 8; pt[2].y = 4 * cy / 8;
Triangle(pdis->hDC, pt);
pt[0].x = 3 * cx / 8; pt[0].y = 5 * cy / 8;
pt[1].x = 5 * cx / 8; pt[1].y = 5 * cy / 8;
pt[2].x = 4 * cx / 8; pt[2].y = 7 * cy / 8;
Triangle(pdis->hDC, pt);
pt[0].x = 3 * cx / 8; pt[0].y = 3 * cy / 8;
pt[1].x = 3 * cx / 8; pt[1].y = 5 * cy / 8;
pt[2].x = 1 * cx / 8; pt[2].y = 4 * cy / 8;
Triangle(pdis->hDC, pt);
break;
}
// Invert the rectangle if the button is selected
if (pdis->itemState & ODS_SELECTED)
InvertRect(pdis->hDC,
&pdis->rcItem);
// Draw a focus rectangle if the button has the focus
if (pdis->itemState & ODS_FOCUS)
{
pdis->rcItem.left += cx / 16;
pdis->rcItem.top += cy / 16;
pdis->rcItem.right -= cx / 16;
pdis->rcItem.bottom -= cy / 16;
DrawFocusRect(pdis->hDC,
&pdis->rcItem);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
在CreateWindow函数中指定窗口类别为「static」,您就可以建立静态文字的子窗口控件。这些子窗口非常「文静」。它既不接收鼠标或键盘输入, 也不向父窗口发送WM_COMMAND消息。
当您在静态子窗口上移动或者按下鼠标时,这个子窗口将拦截WM_NCHITTEST消息并将HTTRANSPARENT的值传回给Windows,这将使Windows向其下层窗口,通常是它的父窗口,发送相同的WM_NCHITTEST消息。父窗口常常将该消息传递给DefWindowProc,在这里,它被转换为显示区域的鼠标消息。
滚动条包括:窗口滚动条和滚动条控件。
与按钮控件(以及将在后面讨论的编辑和清单方块控件)不同,滚动条控件不向父窗口发送WM_COMMAND消息,而是像窗口滚动条那样发送WM_VSCROLL和WM_HSCROLL消息。在处理卷动消息时,您可以通过lParam参数来区分窗口滚动条与滚动条控件。对子窗口滚动条其值为0,对于滚动条控件其值为滚动条窗口句柄。对窗口滚动条和滚动条控件来说,wParam参数的高字组和低字组的含义相同。
取得滚动条的高宽:
GetSystemMetrics (SM_CYHSCROLL) ;
GetSystemMetrics (SM_CXVSCROLL) ;
对窗口滚动条,您可以使用同样的呼叫来建立滚动条控件的范围和位置:
SetScrollRange (hwndScroll, SB_CTL, iMin, iMax, bRedraw) ;
SetScrollPos (hwndScroll, SB_CTL, iPos, bRedraw) ;
SetScrollInfo (hwndScroll, SB_CTL, &si, bRedraw) ;
其区别在于:窗口滚动条将父窗口的句柄作为第一个参数,并且以SB_VERT或者SB_HORZ作为第二个参数。
/*------------------------------------------------------------------------
COLORS1.C -- Colors Using Scroll Bars
(c) Charles Petzold, 1998
-------------------------------------------------------------------------*/
#include
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ScrollProc(HWND, UINT, WPARAM, LPARAM);
int idFocus;
WNDPROC OldScroll[3];
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int
iCmdShow)
{
static TCHAR szAppName[] = TEXT("Colors1");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW |
CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL,
IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,
IDC_ARROW);
wndclass.hbrBackground = CreateSolidBrush(0);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Color Scroll"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM
wParam, LPARAM lParam)
{
static COLORREF crPrim[3] = { RGB(255, 0, 0), RGB(0, 255, 0),
RGB(0, 0, 255) };
static HBRUSH hBrush[3], hBrushStatic;
static HWND hwndScroll[3], hwndLabel[3], hwndValue[3],
hwndRect;
static int color[3], cyChar;
static RECT rcColor;
static TCHAR *szColorLabel[] = { TEXT("Red"), TEXT("Green"),
TEXT("Blue") };
HINSTANCE hInstance;
int i, cxClient, cyClient;
TCHAR szBuffer[10];
switch (message)
{
case WM_CREATE:
hInstance = (HINSTANCE)GetWindowLong(hwnd,
GWL_HINSTANCE);
// SS_WHITERECT样式的静态子窗口,作为三个滚动条的背景
// 子窗口ID is 9.
hwndRect = CreateWindow(TEXT("static"), NULL,
WS_CHILD | WS_VISIBLE | SS_WHITERECT,
0, 0, 0, 0,
hwnd, (HMENU)9, hInstance, NULL);
for (i = 0; i < 3; i++)
{
// 三个滚动条控件,窗口IDs 0, 1, and 2, with
// 设置WS_TABSTOP才可以Tab切换焦点
hwndScroll[i] = CreateWindow(TEXT("scrollbar"), NULL,
WS_CHILD | WS_VISIBLE |
WS_TABSTOP | SBS_VERT,
0, 0, 0, 0,
hwnd, (HMENU)i, hInstance, NULL);
SetScrollRange(hwndScroll[i], SB_CTL, 0, 255,
FALSE);
SetScrollPos(hwndScroll[i], SB_CTL, 0, FALSE);
// 三个颜色静态窗口:红绿蓝,ID是3,4,5
hwndLabel[i] = CreateWindow(TEXT("static"), szColorLabel[i],
WS_CHILD | WS_VISIBLE | SS_CENTER,
0, 0, 0, 0,
hwnd, (HMENU)(i + 3),
hInstance, NULL);
// 三个色值文本静态子窗口 IDs 6, 7,
// and 8, and initial text strings of "0".
hwndValue[i] = CreateWindow(TEXT("static"), TEXT("0"),
WS_CHILD | WS_VISIBLE | SS_CENTER,
0, 0, 0, 0,
hwnd, (HMENU)(i + 6),
hInstance, NULL);
// 通过GWL_WNDPROC参数,设置新的窗口消息处理程序(窗口子类化)
// 这样可以挂钩
OldScroll[i] = (WNDPROC)SetWindowLong
(hwndScroll[i],
GWL_WNDPROC, (LONG)ScrollProc);
// 定义画刷
hBrush[i] = CreateSolidBrush(crPrim[i]);
}
hBrushStatic = CreateSolidBrush(
GetSysColor(COLOR_BTNHIGHLIGHT));
cyChar = HIWORD(GetDialogBaseUnits());
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
SetRect(&rcColor, cxClient / 2, 0, cxClient, cyClient);
MoveWindow(hwndRect, 0, 0, cxClient / 2, cyClient, TRUE);
for (i = 0; i < 3; i++)
{
MoveWindow(hwndScroll[i],
(2 * i + 1) * cxClient / 14, 2 * cyChar,
cxClient / 14, cyClient - 4 * cyChar, TRUE);
MoveWindow(hwndLabel[i],
(4 * i + 1) * cxClient / 28, cyChar / 2, cxClient / 7, cyChar, TRUE);
MoveWindow(hwndValue[i],
(4 * i + 1) * cxClient / 28,
cyClient - 3 * cyChar / 2,
cxClient / 7, cyChar, TRUE);
}
SetFocus(hwnd);
return 0;
case WM_SETFOCUS:
SetFocus(hwndScroll[idFocus]);
return 0;
case WM_VSCROLL:
// 获得子窗口ID
i = GetWindowLong((HWND)lParam, GWL_ID);
switch (LOWORD(wParam))
{
case SB_PAGEDOWN:
color[i] += 15;
// fall through
case SB_LINEDOWN:
color[i] = min(255, color[i] + 1);
break;
case SB_PAGEUP:
color[i] -= 15;
// fall through
case SB_LINEUP:
color[i] = max(0, color[i] - 1);
break;
case SB_TOP:
color[i] = 0;
break;
case SB_BOTTOM:
color[i] = 255;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
color[i] = HIWORD(wParam);
break;
default:
break;
}
// 设置滚动的位置
SetScrollPos(hwndScroll[i], SB_CTL, color[i], TRUE);
// 设置底部文字
wsprintf(szBuffer, TEXT("%i"), color[i]);
SetWindowText(hwndValue[i], szBuffer);
DeleteObject((HBRUSH)
SetClassLong(hwnd,
GCL_HBRBACKGROUND, (LONG)
CreateSolidBrush(RGB(color[0], color[1], color[2]))));
// 无效窗口,强制刷新
InvalidateRect(hwnd, &rcColor, TRUE);
return 0;
case WM_CTLCOLORSCROLLBAR:
i = GetWindowLong((HWND)lParam, GWL_ID);
return (LRESULT)hBrush[i];
case WM_CTLCOLORSTATIC:
i = GetWindowLong((HWND)lParam, GWL_ID);
if (i >= 3 && i <= 8) // static text controls
{
SetTextColor((HDC)wParam, crPrim[i % 3]);
SetBkColor((HDC)wParam, GetSysColor
(COLOR_BTNHIGHLIGHT));
return (LRESULT)hBrushStatic;
}
break;
case WM_SYSCOLORCHANGE:
DeleteObject(hBrushStatic);
hBrushStatic = CreateSolidBrush
(GetSysColor(COLOR_BTNHIGHLIGHT));
return 0;
case WM_DESTROY:
// 清除画刷。SetClassLong设置画刷,并返回旧画刷
DeleteObject((HBRUSH)
SetClassLong(hwnd,
GCL_HBRBACKGROUND, (LONG)
GetStockObject(WHITE_BRUSH)));
for (i = 0; i < 3; i++)
DeleteObject(hBrush[i]);
DeleteObject(hBrushStatic);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
LRESULT CALLBACK ScrollProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int id = GetWindowLong(hwnd, GWL_ID);
switch (message)
{
case WM_KEYDOWN:
if (wParam == VK_TAB)
// 设置输入焦点
SetFocus(GetDlgItem(GetParent
(hwnd),
(id + (GetKeyState(VK_SHIFT) < 0 ? 2 : 1)) % 3));
break;
case WM_SETFOCUS:
idFocus = id;
break;
}
return CallWindowProc(OldScroll[id], hwnd, message,
wParam, lParam);
}
/*---------------------------------------------------------------------------
POPPAD1.C -- Popup Editor using child window edit box
(c) Charles Petzold, 1998
---------------------------------------------------------------------------*/
#include
#define ID_EDIT 1
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
TCHAR szAppName[] = TEXT("PopPad1");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style =
CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon
(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor
(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)
GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM
wParam, LPARAM lParam)
{
static HWND hwndEdit;
switch (message)
{
case WM_CREATE:
// 创建多行文本编辑器 ES_前缀定义编辑器样式
// ES_MULTILINE 多行
// ES_AUTOHSCROLL 自动水平滚动
// ES_NOHIDESEL 没有输入焦点时被选择的文字仍然被加亮
hwndEdit = CreateWindow(TEXT("edit"), NULL,
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
WS_BORDER | ES_LEFT | ES_MULTILINE |
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0, 0, 0, 0, hwnd, (HMENU)ID_EDIT,
((LPCREATESTRUCT)lParam)->hInstance, NULL);
return 0;
case WM_SETFOCUS:
SetFocus(hwndEdit);
return 0;
case WM_SIZE:
// 编辑控件的尺寸
MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam),
TRUE);
return 0;
case WM_COMMAND:
if (LOWORD(wParam) == ID_EDIT)
if (HIWORD(wParam) == EN_ERRSPACE ||
HIWORD(wParam) == EN_MAXTEXT)
MessageBox(hwnd, TEXT("Edit control out of space."),
szAppName, MB_OK | MB_ICONSTOP);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
/*----------------------------------------
ENVIRON.C -- Environment List Box
(c) Charles Petzold, 1998
----------------------------------------*/
#include
#define ID_LIST 1
#define ID_TEXT 2
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Environ") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Environment List Box"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
void FillListBox (HWND hwndList)
{
int iLength ;
TCHAR * pVarBlock, * pVarBeg, * pVarEnd, * pVarName ;
pVarBlock = GetEnvironmentStrings () ; // Get pointer to environment block
while (*pVarBlock)
{
if (*pVarBlock != '=') // Skip variable names beginning with '='
{
pVarBeg = pVarBlock ; // Beginning of variable name
while (*pVarBlock++ != '=') ; // Scan until '='
pVarEnd = pVarBlock - 1 ; // Points to '=' sign
iLength = pVarEnd - pVarBeg ; // Length of variable name
// Allocate memory for the variable name and terminating
// zero. Copy the variable name and append a zero.
pVarName = calloc (iLength + 1, sizeof (TCHAR)) ;
CopyMemory (pVarName, pVarBeg, iLength * sizeof (TCHAR)) ;
pVarName[iLength] = '\0' ;
// Put the variable name in the list box and free memory.
SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM) pVarName) ;
free (pVarName) ;
}
while (*pVarBlock++ != '\0') ; // Scan until terminating zero
}
FreeEnvironmentStrings (pVarBlock) ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndList, hwndText ;
int iIndex, iLength, cxChar, cyChar ;
TCHAR * pVarName, * pVarValue ;
switch (message)
{
case WM_CREATE :
cxChar = LOWORD (GetDialogBaseUnits ()) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;
// Create listbox and static text windows.
hwndList = CreateWindow (TEXT ("listbox"), NULL,
WS_CHILD | WS_VISIBLE | LBS_STANDARD,
cxChar, cyChar * 3,
cxChar * 16 + GetSystemMetrics (SM_CXVSCROLL),
cyChar * 5,
hwnd, (HMENU) ID_LIST,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
hwndText = CreateWindow (TEXT ("static"), NULL,
WS_CHILD | WS_VISIBLE | SS_LEFT,
cxChar, cyChar,
GetSystemMetrics (SM_CXSCREEN), cyChar,
hwnd, (HMENU) ID_TEXT,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
FillListBox (hwndList) ;
return 0 ;
case WM_SETFOCUS :
SetFocus (hwndList) ;
return 0 ;
case WM_COMMAND :
if (LOWORD (wParam) == ID_LIST && HIWORD (wParam) == LBN_SELCHANGE)
{
// Get current selection.
iIndex = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ;
iLength = SendMessage (hwndList, LB_GETTEXTLEN, iIndex, 0) + 1 ;
pVarName = calloc (iLength, sizeof (TCHAR)) ;
SendMessage (hwndList, LB_GETTEXT, iIndex, (LPARAM) pVarName) ;
// Get environment string.
iLength = GetEnvironmentVariable (pVarName, NULL, 0) ;
pVarValue = calloc (iLength, sizeof (TCHAR)) ;
GetEnvironmentVariable (pVarName, pVarValue, iLength) ;
// Show it in window.
SetWindowText (hwndText, pVarValue) ;
free (pVarName) ;
free (pVarValue) ;
}
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
/*---------------------------------------------
HEAD.C -- Displays beginning (head) of file
(c) Charles Petzold, 1998
---------------------------------------------*/
#include
#define ID_LIST 1
#define ID_TEXT 2
#define MAXREAD 8192
#define DIRATTR (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM | \
DDL_DIRECTORY | DDL_ARCHIVE | DDL_DRIVES)
#define DTFLAGS (DT_WORDBREAK | DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX)
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ListProc (HWND, UINT, WPARAM, LPARAM) ;
WNDPROC OldList ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("head") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("head"),
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bValidFile ;
static BYTE buffer[MAXREAD] ;
static HWND hwndList, hwndText ;
static RECT rect ;
static TCHAR szFile[MAX_PATH + 1] ;
HANDLE hFile ;
HDC hdc ;
int i, cxChar, cyChar ;
PAINTSTRUCT ps ;
TCHAR szBuffer[MAX_PATH + 1] ;
switch (message)
{
case WM_CREATE :
cxChar = LOWORD (GetDialogBaseUnits ()) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;
rect.left = 20 * cxChar ;
rect.top = 3 * cyChar ;
hwndList = CreateWindow (TEXT ("listbox"), NULL,
WS_CHILDWINDOW | WS_VISIBLE | LBS_STANDARD,
cxChar, cyChar * 3,
cxChar * 13 + GetSystemMetrics (SM_CXVSCROLL),
cyChar * 10,
hwnd, (HMENU) ID_LIST,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
GetCurrentDirectory (MAX_PATH + 1, szBuffer) ;
hwndText = CreateWindow (TEXT ("static"), szBuffer,
WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT,
cxChar, cyChar, cxChar * MAX_PATH, cyChar,
hwnd, (HMENU) ID_TEXT,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
// 窗口子类,使用回调函数ListProc
OldList = (WNDPROC) SetWindowLong (hwndList, GWL_WNDPROC,
(LPARAM) ListProc) ;
SendMessage (hwndList, LB_DIR, DIRATTR, (LPARAM) TEXT ("*.*")) ;
return 0 ;
case WM_SIZE :
rect.right = LOWORD (lParam) ;
rect.bottom = HIWORD (lParam) ;
return 0 ;
case WM_SETFOCUS :
SetFocus (hwndList) ;
return 0 ;
case WM_COMMAND :
if (LOWORD (wParam) == ID_LIST && HIWORD (wParam) == LBN_DBLCLK)
{
if (LB_ERR == (i = SendMessage (hwndList, LB_GETCURSEL, 0, 0)))
break ;
SendMessage (hwndList, LB_GETTEXT, i, (LPARAM) szBuffer) ;
// 使用CreateFile来检查是目录还是文件
if (INVALID_HANDLE_VALUE != (hFile = CreateFile (szBuffer,
GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL)))
{
CloseHandle (hFile) ;
bValidFile = TRUE ;
lstrcpy (szFile, szBuffer) ;
GetCurrentDirectory (MAX_PATH + 1, szBuffer) ;
if (szBuffer [lstrlen (szBuffer) - 1] != '\\')
lstrcat (szBuffer, TEXT ("\\")) ;
SetWindowText (hwndText, lstrcat (szBuffer, szFile)) ;
}
else
{
bValidFile = FALSE ;
szBuffer [lstrlen (szBuffer) - 1] = '\0' ;
// If setting the directory doesn't work, maybe it's
// a drive change, so try that.
// SetCurrentDirectory不能执行就是磁盘驱动
if (!SetCurrentDirectory (szBuffer + 1))
{
szBuffer [3] = ':' ;
szBuffer [4] = '\0' ;
// 如果是磁盘驱动,则要去掉开头斜线,并加上一个冒号
SetCurrentDirectory (szBuffer + 2) ;
}
// Get the new directory name and fill the list box.
// GetCurrentDirectory返回文件句柄
GetCurrentDirectory (MAX_PATH + 1, szBuffer) ;
SetWindowText (hwndText, szBuffer) ;
SendMessage (hwndList, LB_RESETCONTENT, 0, 0) ;
SendMessage (hwndList, LB_DIR, DIRATTR,
(LPARAM) TEXT ("*.*")) ;
}
InvalidateRect (hwnd, NULL, TRUE) ;
}
return 0 ;
case WM_PAINT :
if (!bValidFile)
break ;
if (INVALID_HANDLE_VALUE == (hFile = CreateFile (szFile, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)))
{
bValidFile = FALSE ;
break ;
}
ReadFile (hFile, buffer, MAXREAD, &i, NULL) ;
CloseHandle (hFile) ;
// i now equals the number of bytes in buffer.
// Commence getting a device context for displaying text.
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT)) ;
SetBkColor (hdc, GetSysColor (COLOR_BTNFACE)) ;
// 假设文件是ASCII编码的
DrawTextA (hdc, buffer, i, &rect, DTFLAGS) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
LRESULT CALLBACK ListProc (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
if (message == WM_KEYDOWN && wParam == VK_RETURN)
SendMessage (GetParent (hwnd), WM_COMMAND,
MAKELONG (1, LBN_DBLCLK), (LPARAM) hwnd) ;
return CallWindowProc (OldList, hwnd, message, wParam, lParam) ;
}