windows 消息循环
- 窗口中发生的一切都以消息的形式传给窗口
消息处理程序。然后,窗口消息处理程序以某种方式响应这个消息,或者将消息传给DefWindowProc,进行内定处理。 - Windows程序也是一个消息循环
它呼叫GetMessage从消息队列中取出消息,并且呼叫dispatchMessage将消息发送给窗口消息处理程序。 - 消息能够被分为「队列化的」和「非队列化的」
队列化的消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新传回并分配给窗口消息处理程序。非队列化的消息在Windows呼叫窗口时直接送给窗口消息处理程序。队列化消息基本上是使用者输入的结果,以击键(如WM_KEYDOWN和WM_KEYUP消息)、击键产生的字符(WM_CHAR)、鼠标移(WM_MOUSEMOVE)和鼠标按钮(WM_LBUTTONDOWN)的形式给出。队列化消息还包含时钟消息(WM_TIMER)、更新消息(WM_PAINT)和退出消息(WM_QUIT)。。在许多情况下,非队列化消息来自呼叫特定的Windows函数。例如,当WinMain呼叫CreateWindow时
输出文字
图形设备接口(GDI)函数
textout (hdc, x, y, psText, iLength) ;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WParaM wParam, LParaM lParam)
{
int wmId, wmEvent;
static int cxChar, cxCaps, cyChar ;
HDC hdc ;
int i ;
PAINTSTRUCT ps ;
TCHAR szBuffer [10] ;
TEXTMETRIC tm ;
RECT rect;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hWnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hWnd, hdc) ;
::SetwindowText(hWnd,_T("test"));
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBox), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
{
hdc = BeginPaint (hWnd, &ps) ;
for (i = 0 ; i < NUMLInes ; i++)
{
SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
textout (hdc, 0, cyChar * i,
sysmetrics[i].szLabel,
lstrlen (sysmetrics[i].szLabel)) ;
textout (hdc, 22 * cxCaps, cyChar * i,
sysmetrics[i].szDesc,
lstrlen (sysmetrics[i].szDesc)) ;
SetTextAlign (hdc, TA_LEFT| TA_TOP) ;
textout (hdc, 22 * cxCaps + 40 * cxChar, cyChar * i, szBuffer,
wsprintf (szBuffer, TEXT ("%d"),
GetSystemMetrics (sysmetrics[i].iIndex))) ;
SetTextAlign (hdc, TA_LEFT| TA_TOP) ;
}
EndPaint (hWnd, &ps) ;
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
字体的设置
typedef struct tagTEXTMETRIC
{
LONG tmHeight ;
LONG tmAscent ;
LONG tmDescent ;
LONG tmInternalLeading ;
LONG tmExternalLeading ;
LONG tmAveCharWidth ;
LONG tmMaxCharWidth ;
//其它结构字段
}
TEXTMETRIC, * PTEXTMETRIC ;
TEXTMETRIC tm ;
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
ReleaseDC (hwnd, hdc) ;
取得设备内容
typedef struct tagPAINTSTRUCT
{
HDC hdc ; //设备
BOOL fErase ; //擦除无效矩形的背景
RECT rcPaint ;
BOOL fRestore ;
BOOL fIncUpdate ;
BYTE rgbReserved[32] ;
} PAINTSTRUCT ;
hdc = GetDC (hwnd) ;
//使用GDI函数
ReleaseDC (hwnd, hdc) ;
与GetDC相似的函数是GetwindowDC。GetDC传回用于写入窗口显示区域的设备内容句
柄 , 而 GetwindowDC 传 回 写 入 整 个 窗 口 的 设 备 内 容 句 柄 。 例 如 , 您 的 程 序 可 以 使 用 从
GetwindowDC传回的设备内容句柄在窗口的标题栏上写入文字。然而,程序同样也应该处理
WM_NCPAINT (「非显示区域绘制」)消息
滚动条
结构
typedef struct tagSCROLLINFO
{
UINT cbSize;//设置为sizeof(SCROLLINFO)
UINT fMask;//要设置或获取的值
int nMin;//范围的最小值
int nMax;//范围的最大值
UINT nPage;//页面大小
int nPos;//当前位置
int nTrackPos;//当前追踪位置
} SCROLLINFO, FAR *LPSCROLLINFO;
hwnd = CreateWindow (szAppName, TEXT ("Get System Metrics No. 2"),
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WParaM wParam, LParaM lParam)
{
static int cxChar, cxCaps, cyChar, cyClient, iVscrollPos ;
HDC hdc ;
int i, y ;
PAINTSTRUCT ps ;
TCHAR szBuffer[10] ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
SetScrollRange (hwnd, SB_VERT, 0, NUMLInes - 1, FALSE) ;
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
return 0 ;
case WM_SIZE:
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_VSCROLL:
switch (LOWORD (wParam))
{
case SB_LINEUP:
iVscrollPos -= 1 ;
break ;
case SB_LINEDOWN:
iVscrollPos += 1 ;
break ;
case SB_PAGEUP:
iVscrollPos -= cyClient / cyChar ;
break ;
case SB_PAGEDOWN:
iVscrollPos += cyClient / cyChar ;
break ;
case SB_THUMBPOSITION:
iVscrollPos = HIWORD (wParam) ;
break ;
default :
break ;
}
iVscrollPos = max (0, min (iVscrollPos, NUMLInes - 1)) ;
if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))
{
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
InvalidateRect (hwnd, NULL, TRUE) ;
}
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
for (i = 0 ; i < NUMLInes ; i++)
{
y = cyChar * (i - iVscrollPos) ;
textout (hdc, 0, y,
sysmetrics[i].szLabel,
lstrlen (sysmetrics[i].szLabel)) ;
textout (hdc, 22 * cxCaps, y,
sysmetrics[i].szDesc,
lstrlen (sysmetrics[i].szDesc)) ;
SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;
textout (hdc, 22 * cxCaps + 40 * cxChar, y, szBuffer,
wsprintf (szBuffer, TEXT ("%5d"),
GetSystemMetrics (sysmetrics[i].iIndex))) ;
SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
//=====================================================直接进行设置==========================================
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WParaM wParam, LParaM lParam)
{
static int cxChar, cxCaps, cyChar, cyClient, iVscrollPos ;
HDC hdc ;
int i, y ;
PAINTSTRUCT ps ;
TCHAR szBuffer[10] ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
SetScrollRange (hwnd, SB_VERT, 0, NUMLInes - 1, FALSE) ;
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
return 0 ;
case WM_SIZE:
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_VSCROLL:
switch (LOWORD (wParam))
{
case SB_LINEUP:
iVscrollPos -= 1 ;
break ;
case SB_LINEDOWN:
iVscrollPos += 1 ;
break ;
case SB_PAGEUP:
iVscrollPos -= cyClient / cyChar ;
break ;
case SB_PAGEDOWN:
iVscrollPos += cyClient / cyChar ;
break ;
case SB_THUMBPOSITION:
iVscrollPos = HIWORD (wParam) ;
break ;
default :
break ;
}
iVscrollPos = max (0, min (iVscrollPos, NUMLInes - 1)) ;
if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))
{
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
InvalidateRect (hwnd, NULL, TRUE) ;
}
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
for (i = 0 ; i < NUMLInes ; i++)
{
y = cyChar * (i - iVscrollPos) ;
textout (hdc, 0, y,
sysmetrics[i].szLabel,
lstrlen (sysmetrics[i].szLabel)) ;
textout (hdc, 22 * cxCaps, y,
sysmetrics[i].szDesc,
lstrlen (sysmetrics[i].szDesc)) ;
SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;
textout (hdc, 22 * cxCaps + 40 * cxChar, y, szBuffer,
wsprintf (szBuffer, TEXT ("%5d"),
GetSystemMetrics (sysmetrics[i].iIndex))) ;
SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
相关函数
- SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ;
- SetScrollPos (hwnd, iBar, iPos, bRedraw) ;
ibar 滚动条的类型 参数iBar为SB_VERT或者SB_HORZ
iMin和iMax分别是范围的最小值和最大值
Windows根据新范围重画滚动条,则设置bRedraw为TRUE
(GetScrollRange和GetScrollPos)来取得滚动条的目前范围和位置
所具有的消息的类型
case WM_VSCROLL:
switch (LOWORD (wParam))
{
case SB_LINEUP:
iVscrollPos -= 1 ;
break ;
case SB_LINEDOWN:
iVscrollPos += 1 ;
break ;
case SB_PAGEUP:
iVscrollPos -= cyClient / cyChar ;
break ;
case SB_PAGEDOWN:
iVscrollPos += cyClient / cyChar ;
break ;
case SB_THUMBPOSITION:
iVscrollPos = HIWORD (wParam) ;
break ;
default :
break ;
}
iVscrollPos = max (0, min (iVscrollPos, NUMLInes - 1)) ;
if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))
{
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
InvalidateRect (hwnd, NULL, TRUE) ;
}
return 0 ;
图形基础
GDI基本操作
取得设备内容句柄
hdc = GetDC (hwnd) ;
hdc = GetwindowDC (hwnd) ;
ReleaseDC (hwnd, hdc) ;
通用的做法有
hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData) ;
//其它行程序
DeleteDC (hdc) ;
as
hdc = CreateDC (TEXT (“disPLAY”), NULL, NULL, NULL) ;
取得设备内容信息
iValue = GetDeviceCaps (hdc, iIndex) ;其中,参数iIndex取值为WINGDI.H表头文件中定义的29个标识符之一。例如,iIndex为HORZRES时将使GetDeviceCaps传回设备的宽度(单位为像素);
==画点和线 ==
这部分用到再看
键盘
iState = GetKeyState (VK_SHIFT) ;
case WM_KEYDOWN:
switch (wParam)
{
case VK_HOME:
SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0) ;
break ;
case VK_END:
SendMessage (hwnd, WM_VSCROLL, SB_BottOM, 0) ;
break ;
case VK_PRIOR:
SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0) ;
break ;
case VK_NEXT:
SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0) ;
break ;
case VK_UP:
SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0) ;
break ;
case VK_DOWN:
SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN, 0) ;
break ;
case VK_LEFT:
SendMessage (hwnd, WM_HSCROLL, SB_PAGEUP, 0) ;
break ;
case VK_RIGHT:
SendMessage (hwnd, WM_HSCROLL, SB_PAGEDOWN, 0) ;
break ;
}
return 0 ;
插入符号
需要的时候再看
鼠标
函数
fMouse = GetSystemMetrics (SM_MOUSEPRESENT) ;//鼠标是都存在
cButtons = GetSystemMetrics (SM_CMOUSEBUTTONS) ; //鼠标的按键的个数
光标的类型
IDC_ARROW斜箭头
IDC_CROSS等
进程定义位置wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
术语
Clicking按下并放开一个鼠标按键。
Double-clicking快速按下并放开鼠标按键两次。
Dragging按住鼠标按键并移动鼠标。
LBUTTON、MBUTTON和RBUTTON左键,中键,以及右键
消息WM_LBUTTONDOWN等
对于所有这些消息来说,其lParam值均含有鼠标的位置:低字组为x坐标,高字组为y坐标,这两个坐标是相对于窗口显示区域左上角的位置。您可以用LOWORD和HIWORD宏来提取这些值:
x = LOWORD (lParam) ;
y = HIWORD (lParam) ;
wParam的值指示鼠标按键以及Shift和Ctrl键的状态,wparam & MK_SHIFT是TRUE(非0),您就知道当左键按下时也按下了Shift键。
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ; 此时支持双击
使用键盘仿真鼠标
GetCursorPos (&pt) ;
SetCursorPos (x, y) ;
定时器
SetTimer
KillTimer
但并不是很精确的时间中断
定时器的使用
- way one
SetTimer (hwnd, 1, uimsecInterval, NULL) ; 句柄,timer的id,时间间隔,callback函数(处理定时器)
KillTimer (hwnd, 1) ;
case WM_TIMER:
switch (wParam)
{
case 1000:
//每秒一次的处理
break ;
case 60000:
//每分钟一次的处理
break ;
}
return 0 ;
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WParaM wParam, LParaM lParam)
{
static BOOL fFlipFlop = FALSE ;
HBrush hBrush ;
HDC hdc ;
PAINTSTRUCT ps ;
RECT rc ;
switch (message)
{
case WM_CREATE:
SetTimer (hwnd, ID_TIMER, 1000, NULL) ;
return 0 ;
case WM_TIMER :
fFlipFlop = !fFlipFlop ;
InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rc) ;
hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ;
FillRect (hdc, &rc, hBrush) ;
EndPaint (hwnd, &ps) ;
DeleteObject (hBrush) ;
return 0 ;
case WM_DESTROY :
KillTimer (hwnd, ID_TIMER) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
- way two
第二种方法
是让Windows直接将定时器消息发送给您程序的另一个函数。
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WParaM wParam, LParaM lParam)
{
switch (message)
{
case WM_CREATE:
SetTimer (hwnd, ID_TIMER, 1000, TimerProc) ;
return 0 ;
case WM_DESTROY:
KillTimer (hwnd, ID_TIMER) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
VOID CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
static BOOL fFlipFlop = FALSE ;
HBrush hBrush ;
HDC hdc ;
RECT rc ;
MessageBeep (-1) ;
fFlipFlop = !fFlipFlop ;
GetClientRect (hwnd, &rc) ;
hdc = GetDC (hwnd) ;
hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ;
FillRect (hdc, &rc, hBrush) ;
ReleaseDC (hwnd, hdc) ;
DeleteObject (hBrush) ;
}
定时器的使用示例
typedef struct _SYstemTIME
{
WORD wYear ;
WORD wMonth ;
WORD wDayOfWeek ;
WORD wDay ;
WORD wHour ;
WORD wMinute ;
WORD wSecond ;
WORD wMilliseconds ;
}
SYstemTIME, * PSYstemTIME ;
GetLocalTime (&st) ;
#include <windows.h>
#define ID_TIMER 1
LRESULT CALLBACK WndProc (HWND, UINT, WParaM, LParaM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdshow)
{
static TCHAR szAppName[] = TEXT ("DigClock") ;
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 ("Program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Digital Clock"),
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 displayDigit (HDC hdc, int iNumber)
{
static BOOL fSevenSegment [10][7] = {
1, 1, 1, 0, 1, 1, 1, // 0
0, 0, 1, 0, 0, 1, 0, // 1
1, 0, 1, 1, 1, 0, 1, // 2
1, 0, 1, 1, 0, 1, 1, // 3
0, 1, 1, 1, 0, 1, 0, // 4
1, 1, 0, 1, 0, 1, 1, // 5
1, 1, 0, 1, 1, 1, 1, // 6
1, 0, 1, 0, 0, 1, 0, // 7
1, 1, 1, 1, 1, 1, 1, // 8
1, 1, 1, 1, 0, 1, 1 } ; // 9
static POINT ptSegment [7][6] = {
7, 6, 11, 2, 31, 2, 35, 6, 31, 10, 11, 10,
6, 7, 10, 11, 10, 31, 6, 35, 2, 31, 2, 11,
36, 7, 40, 11, 40, 31, 36, 35, 32, 31, 32, 11,
7, 36, 11, 32, 31, 32, 35, 36, 31, 40, 11, 40,
6, 37, 10, 41, 10, 61, 6, 65, 2, 61, 2, 41,
36, 37, 40, 41, 40, 61, 36, 65, 32, 61, 32, 41,
7, 66, 11, 62, 31, 62, 35, 66, 31, 70, 11, 70 } ;
int iSeg ;
for (iSeg = 0 ; iSeg < 7 ; iSeg++)
if (fSevenSegment [iNumber][iSeg])
polygon (hdc, ptSegment [iSeg], 6) ;
}
void displayTwoDigits (HDC hdc, int iNumber, BOOL fSuppress)
{
if (!fSuppress || (iNumber / 10 != 0))
displayDigit (hdc, iNumber / 10) ;
OffsetwindowOrgEx (hdc, -42, 0, NULL) ;
displayDigit (hdc, iNumber % 10) ;
OffsetwindowOrgEx (hdc, -42, 0, NULL) ;
}
void displayColon (HDC hdc)
{
POINT ptColon [2][4] = { 2, 21, 6, 17, 10, 21, 6, 25,
2, 51, 6, 47, 10, 51, 6, 55 } ;
polygon (hdc, ptColon [0], 4) ;
polygon (hdc, ptColon [1], 4) ;
OffsetwindowOrgEx (hdc, -12, 0, NULL) ;
}
void displayTime (HDC hdc, BOOL f24Hour, BOOL fSuppress)
{
SYstemTIME st ;
GetLocalTime (&st) ;
if (f24Hour)
displayTwoDigits (hdc, st.wHour, fSuppress) ;
else
displayTwoDigits (hdc, (st.wHour %= 12) ? st.wHour : 12, fSuppress) ;
displayColon (hdc) ;
displayTwoDigits (hdc, st.wMinute, FALSE) ;
displayColon (hdc) ;
displayTwoDigits (hdc, st.wSecond, FALSE) ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WParaM wParam, LParaM lParam)
{
static BOOL f24Hour, fSuppress ;
static HBrush hBrushred ;
static int cxClient, cyClient ;
HDC hdc ;
PAINTSTRUCT ps ;
TCHAR szBuffer [2] ;
switch (message)
{
case WM_CREATE:
hBrushred = CreateSolidBrush (RGB (255, 0, 0)) ;
SetTimer (hwnd, ID_TIMER, 1000, NULL) ;
// fall through
case WM_SETTINGCHANGE:
GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 2) ;
f24Hour = (szBuffer[0] == '1') ;
GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ITLZERO, szBuffer, 2) ;
fSuppress = (szBuffer[0] == '0') ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_TIMER:
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
SetMapMode (hdc, MM_ISOTROPIC) ;
SetwindowExtEx (hdc, 276, 72, NULL) ;
SetViewportExtEx (hdc, cxClient, cyClient, NULL) ;
SetwindowOrgEx (hdc, 138, 36, NULL) ;
SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;
SelectObject (hdc, GetStockObject (NULL_PEN)) ;
SelectObject (hdc, hBrushred) ;
displayTime (hdc, f24Hour, fSuppress) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
KillTimer (hwnd, ID_TIMER) ;
DeleteObject (hBrushred) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
/*--------------------------------------
CLOCK.C -- Analog Clock Program
(c) Charles Petzold, 1998
--------------------------------------*/
#include <windows.h>
#include <math.h>
#define ID_TIMER 1
#define TWOPI (2 * 3.14159)
LRESULT CALLBACK WndProc (HWND, UINT, WParaM, LParaM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdshow)
{
static TCHAR szAppName[] = TEXT ("Clock") ;
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 = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBrush) GetStockObject (WHITE_Brush) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("Program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Analog Clock"),
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 SetIsotropic (HDC hdc, int cxClient, int cyClient)
{
SetMapMode (hdc, MM_ISOTROPIC) ;
SetwindowExtEx (hdc, 1000, 1000, NULL) ;
SetViewportExtEx (hdc, cxClient / 2, -cyClient / 2, NULL) ;
SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;
}
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 ;
}
}
void DrawClock (HDC hdc)
{
int iAngle ;
POINT pt[3] ;
for (iAngle = 0 ; iAngle < 360 ; iAngle += 6)
{
pt[0].x = 0 ;
pt[0].y = 900 ;
RotatePoint (pt, 1, iAngle) ;
pt[2].x = pt[2].y = iAngle % 5 ? 33 : 100 ;
pt[0].x -= pt[2].x / 2 ;
pt[0].y -= pt[2].y / 2 ;
pt[1].x = pt[0].x + pt[2].x ;
pt[1].y = pt[0].y + pt[2].y ;
SelectObject (hdc, GetStockObject (BLACK_Brush)) ;
Ellipse (hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y) ;
}
}
void DrawHands (HDC hdc, SYstemTIME * pst, BOOL fChange)
{
static POINT pt[3][5] = { 0, -150, 100, 0, 0, 600, -100, 0, 0, -150,
0, -200, 50, 0, 0, 800, -50, 0, 0, -200,
0, 0, 0, 0, 0, 0, 0, 0, 0, 800 } ;
int i, iAngle[3] ;
POINT ptTemp[3][5] ;
iAngle[0] = (pst->wHour * 30) % 360 + pst->wMinute / 2 ;
iAngle[1] = pst->wMinute * 6 ;
iAngle[2] = pst->wSecond * 6 ;
memcpy (ptTemp, pt, sizeof (pt)) ;
for (i = fChange ? 0 : 2 ; i < 3 ; i++)
{
RotatePoint (ptTemp[i], 5, iAngle[i]) ;
polyline (hdc, ptTemp[i], 5) ;
}
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WParaM wParam, LParaM lParam)
{
static int cxClient, cyClient ;
static SYstemTIME stPrevIoUs ;
BOOL fChange ;
HDC hdc ;
PAINTSTRUCT ps ;
SYstemTIME st ;
switch (message)
{
case WM_CREATE :
SetTimer (hwnd, ID_TIMER, 1000, NULL) ;
GetLocalTime (&st) ;
stPrevIoUs = st ;
return 0 ;
case WM_SIZE :
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_TIMER :
GetLocalTime (&st) ;
fChange = st.wHour != stPrevIoUs.wHour ||
st.wMinute != stPrevIoUs.wMinute ;
hdc = GetDC (hwnd) ;
SetIsotropic (hdc, cxClient, cyClient) ;
SelectObject (hdc, GetStockObject (WHITE_PEN)) ;
DrawHands (hdc, &stPrevIoUs, fChange) ;
SelectObject (hdc, GetStockObject (BLACK_PEN)) ;
DrawHands (hdc, &st, TRUE) ;
ReleaseDC (hwnd, hdc) ;
stPrevIoUs = st ;
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
SetIsotropic (hdc, cxClient, cyClient) ;
DrawClock (hdc) ;
DrawHands (hdc, &stPrevIoUs, TRUE) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY :
KillTimer (hwnd, ID_TIMER) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
子窗口控件
hwndParent = GetParent (hwnd) ;
其中,hwnd是子窗口的窗口句柄。它可以向其父窗口消息处理程序发送消息:
SendMessage (hwndParent, message, wParam, lParam) ;
以后用到再说。。。
菜单及其他资源
对话框
剪贴簿
使用打印机
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。