windows程序设计

windows 消息循环

  1. 窗口中发生的一切都以消息的形式传给窗口
    消息处理程序。然后,窗口消息处理程序以某种方式响应这个消息,或者将消息传给DefWindowProc,进行内定处理。
  2. Windows程序也是一个消息循环
    它呼叫GetMessage从消息队列中取出消息,并且呼叫dispatchMessage将消息发送给窗口消息处理程序。
  3. 消息能够被分为「队列化的」和「非队列化的」
    队列化的消息是由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) ;
}

相关函数

  1. SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ;
  2. 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
但并不是很精确的时间中断
定时器的使用

  1. 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) ;
}
  1. 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) ;
以后用到再说。。。

菜单及其他资源

对话框

剪贴簿

使用打印机

相关文章

Windows2012R2备用域控搭建 前置操作 域控主域控的主dns:自...
主域控角色迁移和夺取(转载) 转载自:http://yupeizhi.blo...
Windows2012R2 NTP时间同步 Windows2012R2里没有了internet时...
Windows注册表操作基础代码 Windows下对注册表进行操作使用的...
黑客常用WinAPI函数整理之前的博客写了很多关于Windows编程的...
一个简单的Windows Socket可复用框架说起网络编程,无非是建...