首页 > 代码库 > SDK源码分析 1

SDK源码分析 1

  1 #include <windows.h>
  2 
  3 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//回调函数 WndProc;
  4 
  5 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
  6 {
  7 
  8     WNDCLASS wndclass;//窗口类
  9     static TCHAR szWindowsName[]=TEXT("MyWindows"),szClassName[] = TEXT("MyClass");
 10     HWND hWnd;
 11     MSG msg;
 12 
 13     //设置类风格
 14     wndclass.style = CS_VREDRAW | CS_HREDRAW;
 15     wndclass.cbClsExtra = 0;
 16     wndclass.cbWndExtra = 0;
 17     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
 18     wndclass.hCursor = LoadCursor(NULL, IDC_HAND);
 19     wndclass.hIcon = LoadIcon(NULL, IDI_ERROR);
 20     wndclass.hInstance = hInstance;
 21     wndclass.lpfnWndProc = WndProc;
 22     wndclass.lpszClassName = szClassName;
 23     wndclass.lpszMenuName = NULL;
 24     
 25     //注册窗口类
 26     RegisterClass(&wndclass);
 27 
 28     //生成窗口
 29     hWnd=CreateWindow(szClassName, szWindowsName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
 30         NULL, NULL, hInstance, NULL);
 31 
 32     UpdateWindow(hWnd);//更新窗口
 33     ShowWindow(hWnd, iCmdShow);//显示窗口
 34 
 35     //消息循环
 36     while (GetMessage(&msg, NULL, NULL, NULL))
 37     {
 38         TranslateMessage(&msg);//翻译键盘消息
 39         DispatchMessage(&msg);//转发消息到WnProc
 40     }
 41     return msg.wParam;
 42 }
 43 
 44 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 45 {
 46     static int cxClientMax, cyClientMax, cxClient, cyClient, cxChar, cyChar;
 47     static int cLinesMax, cLines;
 48     static PMSG pmsg;
 49     static RECT rectScroll;
 50     static TCHAR szTop[] = TEXT("Message Key Char Repeat Scan Ext ALT Prev Tran");
 51     static TCHAR szUnd[] = TEXT("_______ ___ ____ ______ ____ ___ ___ ____ ____");
 52     static TCHAR * szFormat[2] = {
 53         TEXT("%-13s %3d%-15s%c%6u%4d%3s%3s%4s%4s"),
 54         TEXT("%-13s 0x%04X%1s%c%6u%4d%3s%3s%4s%4s")};
 55     static TCHAR *szYes = TEXT("Yes");
 56     static TCHAR *szNo = TEXT("No");
 57     static TCHAR *szDown = TEXT("Down");
 58     static TCHAR *szUp = TEXT("Up");
 59     static TCHAR *szMessage[] = {
 60         TEXT("WM_KEYDOWN"),TEXT("WM_KEYUP"),
 61         TEXT("WM_CHAR"),TEXT("WM_DEADCHAR"),
 62         TEXT("WM_SYSKEYDOWN"),TEXT("WM_SYSKEYUP"),
 63         TEXT("WM_SYSCHAR"),TEXT("WM_SYSDEADCHAR")
 64     };
 65     int i, iType;
 66     TCHAR szBuffer[128], szKeyName[32];
 67     TEXTMETRIC tm;
 68     PAINTSTRUCT ps;
 69     HDC hdc;
 70 
 71     switch (msg)
 72     {
 73         //WM_CREATE 和 WM_DISPLAYCHANGE 消息共同执行下面代码
 74     case WM_CREATE:
 75     case WM_DISPLAYCHANGE:
 76         //获取 客户端最大宽度
 77         cxClientMax = GetSystemMetrics(SM_CXMAXIMIZED);
 78         //获取 客户端最大高度
 79         cyClientMax = GetSystemMetrics(SM_CYMAXIMIZED);
 80         
 81         hdc = GetDC(hWnd);
 82         //设置当前hdc为等款字体
 83         SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
 84         //获取 文本信息
 85         GetTextMetrics(hdc, &tm);
 86         //设置字符宽度
 87         cxChar = tm.tmAveCharWidth;
 88         //设置字符高度
 89         cyChar = tm.tmHeight;
 90         ReleaseDC(hWnd, hdc);
 91         
 92         
 93         if (pmsg)//如果没有东西
 94         {
 95             free(pmsg);//释放pmsg
 96         }
 97             
 98 
 99         //获取 客户端 最大容量行数  客户端最大高度/字符高度
100         cLinesMax = cyClientMax / cyChar;
101         //生成 内存中 取 MSG 大小的内存 * 客户端最大行数
102         pmsg =(PMSG) malloc(cLinesMax * sizeof(MSG));
103         // 清空当前行数
104         cLines = 0;
105         
106         //继续执行
107     case WM_SIZE:
108         //如果是 WM_SIZE消息
109         if (msg == WM_SIZE)
110         {
111             //获取 客户端宽度
112             cxClient = LOWORD(lParam);
113             //获取 客户端高度
114             cyClient = HIWORD(lParam);
115         }
116         //设置 矩形 左边为 0
117         rectScroll.left = 0;
118         //设置 矩形 右边为 最大客户端宽度
119         rectScroll.right = cxClient;
120         //设置 矩形 顶边 为 字符高度。 因为最上面有 我们的 字符
121         rectScroll.top = cyChar;
122         //设置 矩形 底边 为 字符高度*(客户端高度 /字符高度) 其实没必要 直接 cyClient。书上这样写我不知道为啥
123         rectScroll.bottom = cyChar*(cyClient / cyChar);
124 
125         //失效矩形区域 重画
126         InvalidateRect(hWnd, NULL, TRUE);
127         return 0;//这里返回
128         
129         //下面全部是键盘消息
130     case WM_KEYDOWN:
131     case WM_KEYUP:
132     case WM_CHAR:
133     case WM_DEADCHAR:
134     case WM_SYSKEYDOWN:
135     case WM_SYSKEYUP:
136     case WM_SYSCHAR:
137     case WM_SYSDEADCHAR:
138         
139         //i=客户端最大行数-1 。如果 i>0  那么就 滚动消息
140         for (i = cLinesMax - 1; i > 0; i--)
141         {
142             //滚动消息。
143             pmsg[i] = pmsg[i - 1];
144         }
145         pmsg[0].hwnd = hWnd;
146         pmsg[0].message = msg;
147         pmsg[0].wParam = wParam;
148         pmsg[0].lParam = lParam;
149         //消息 最下面的赋值最新
150         /*
151         比如: 当前 最大行数为 100
152         i=99;    i如果大于 0
153         那么 pmsg[99]=pmsg[98]......
154         pmsg[1]=pmsg[0]; 这时 i=0 取消循环
155         由 WM_PAIN 来重绘 窗口显示内容
156         但是 记住 这里 不管里面有没有消息都是 滚动的。
157         */
158         
159         //下面代码 看起来是 防止 超出内容 其实 是每次累加 cLines的值
160         cLines = min(cLines + 1, cLinesMax);
161         
162         //滚动 矩形区域。以负数形式 向上翻滚 每次翻滚 一个字符高度。
163         ScrollWindow(hWnd, 0, -cyChar, &rectScroll, &rectScroll);
164         break;//跳出 选择
165     case WM_PAINT:
166         hdc=BeginPaint(hWnd, &ps);
167         //设置 字体为等宽字体
168         SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
169         //设置字体为 透明模式
170         SetBkMode(hdc, TRANSPARENT);
171         //画出两行可以叠加的文字
172         TextOut(hdc, 0, 0, szTop, lstrlen(szTop));
173         TextOut(hdc, 0, 0, szUnd, lstrlen(szUnd));
174 
175         //i=0; i 小于  (当前行数,客户端高度/字符高度-1)
176         // 这里的 意思是 如果行数 是 5  在如果 高度为100  字符高度为5
177         //那么 100/5=20  20-1 =19  19是最大能容量的字符个数 如果 前者大于后者 那么 永远 是 19了。
178         for (i = 0; i < min(cLines, cyClient / cyChar - 1); i++)
179         {
180             
181             // 如果 消息[i]的消息是 以下这几个 就赋值 真 否则  为假;
182             iType = pmsg[i].message == WM_CHAR ||
183                 pmsg[i].message == WM_SYSCHAR ||
184                 pmsg[i].message == WM_DEADCHAR ||
185                 pmsg[i].message == WM_SYSDEADCHAR;
186                 
187             //获取 键的 名字文本 。用lParam作为参数 放到szKeyName 第三参数意思为 100/5 =20;
188             GetKeyNameText(pmsg[i].lParam, szKeyName, sizeof(szKeyName) / sizeof(TCHAR));
189             
190             //输出文本 左边为0  顶边为 计算过后的 (客户高度/字符高度-1-i)*字符高度;
191             //比如: 客户高度:100  字符高度:5
192             // 100/5-1 =19 -i 这个i 就是 已经画过了的。为什么最后*cyChar。 因为 这是高度。
193             //画的文本是 szBuffer里面的。但是 现在 szBuffer貌似没有值。
194             // 接下来一个参数 用wsprintf  格式化字符串 到szBuffer里面。iType标记了第几个数组。
195             //szMessage[pmsg[i].message - WM_KEYFIRST], 
196             //意思是第i个消息收到之后 减去 标准消息 为的是方便数组的选取
197             //(PTSTR)(iType ? TEXT(" ") : szKeyName),//判断是否为键消息
198             //(TCHAR)(iType ? pmsg[i].wParam : ‘ ‘),//判断是否为字符消息
199             /*
200             LOWORD(pmsg[i].lParam), HIWORD(pmsg[i].lParam) & 0xFF,
201             0x01000000 & pmsg[i].lParam ? szYes : szNo,
202             0x20000000 & pmsg[i].lParam ? szYes : szNo,
203             0x40000000 & pmsg[i].lParam ? szDown : szUp,
204             0x80000000 & pmsg[i].lParam ? szUp : szDown));
205             以上几句话 对照 键盘的参数 来得出答案。分别是获取 键或者字符的附加参数
206             */
207             TextOut(hdc, 0, (cyClient / cyChar - 1 - i) * cyChar, szBuffer,
208                 wsprintf(szBuffer, szFormat[iType],
209                     szMessage[pmsg[i].message - WM_KEYFIRST], pmsg[i].wParam,
210                     (PTSTR)(iType ? TEXT(" ") : szKeyName),
211                     (TCHAR)(iType ? pmsg[i].wParam :  ),
212                     LOWORD(pmsg[i].lParam), HIWORD(pmsg[i].lParam) & 0xFF,
213                     0x01000000 & pmsg[i].lParam ? szYes : szNo,
214                     0x20000000 & pmsg[i].lParam ? szYes : szNo,
215                     0x40000000 & pmsg[i].lParam ? szDown : szUp,
216                     0x80000000 & pmsg[i].lParam ? szUp : szDown));
217         }
218 
219         //TextOut(hdc, 0, 0, TEXT("这是一个标准的C语言Windows窗口."), lstrlen(TEXT("这是一个标准的C语言Windows窗口.")));
220 
221         EndPaint(hWnd, &ps);
222         return 0;
223     case WM_DESTROY:
224         PostQuitMessage(0);
225         return 0;
226     }
227     return DefWindowProc(hWnd, msg, wParam, lParam);
228 }

 

SDK源码分析 1