用VC MFC有一段时间了,总觉得还没掌握到精髓,项目代码基本是拼凑起来的。总是少点什么。前段时间,看完 快乐鹦鹉 的程序人生, 里面提到 全局变量 的一段。突然想到自己用 vc+opencv的一个小项目, 那里面真可谓 全局变量满天飞啊,只要是mat 的变量都成了全局变量,方便访问。总觉得自己以前写程序,纯属为写而写, 只要能达到目标,怎么直接怎么来,很是野蛮的方式。对写程序缺乏一个系统的研究,基础不牢固。很有必要,系统的看看相关书籍了。
1、注册窗口类时,类的名称不能重复,当前面已经注册了一个名字的类(lpszClassName),后面的窗口类就不能再用这个名字了。
以下代码用 szAppName[] 及szAppName1[] 放置两个类名字符串,若szAppName1[] 的内容与szAppName[]一样时,在第二次注册时不会成功,由GetLastError()的返回值是1410 可以到 〖1410〗-类别已存在。
#include <windows.h>
#include <tchar.h>
#include <mmsystem.h>
#pragma comment(lib, "WINMM.LIB")
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
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 ;
static TCHAR szAppName1[] = TEXT("HelloWin");
HWND hwnd1;
WNDCLASS wndclass1;
wndclass1.style = CS_HREDRAW | CS_VREDRAW;
wndclass1.lpfnWndProc = WndProc;
wndclass1.cbClsExtra = 0;
wndclass1.cbWndExtra = 0;
wndclass1.hInstance = hInstance;
wndclass1.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass1.hCursor = LoadCursor(NULL, IDC_WAIT);
wndclass1.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndclass1.lpszMenuName = NULL;
wndclass1.lpszClassName = szAppName1;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
if (!RegisterClass(&wndclass1))
{
GetLastError();
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName1, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
hwnd1 = CreateWindow(szAppName1, // window class name
TEXT("The Hello Program1"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hwnd1, iCmdShow);
UpdateWindow(hwnd1);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:
PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
TextOut(hdc, 0, 0, _T("您好!测试一下数量"), 9);
DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
case WM_LBUTTONDOWN:
PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
return 0;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
2、上述程序TextOut(hdc,0,0,_T("您好!测试下数量"),9) 针对函数TextOut的试验。
a、TextOut并不认为字符串尾部值为0字节表示字符串的结束,它利用iLength参数来决定字符串的长度,把9该大时将会出现乱码
b、去掉_T() ,也是出现乱码, unicode双字节字符串。
c、确定打印个数时,可以使用 lstrlen() 获得;
3、消息中处理的变量,若是有连续性或其他地方需要使用,该变量应声明为静态变量。因为消息结束时,消息中的变量也会随之释放,将上面的回调函数改为:
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
TCHAR szAppName[] = TEXT("大王叫我来寻山!");
static int lButtonDownTimes = 0;
int rButtonDownTimes = 0;
static TCHAR timesDown[100];
static TCHAR timesRDown[100];
switch (message)
{
case WM_CREATE:
PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
TextOut(hdc, 0, 0, timesDown, 10);
TextOut(hdc, 0, 10, timesRDown, 10);
DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
case WM_LBUTTONDOWN:
wsprintf(timesDown, _T("左键按下次数:%d"), lButtonDownTimes);
InvalidateRect(hwnd,NULL,TRUE);
lButtonDownTimes++;
return 0;
case WM_RBUTTONDOWN:
wsprintf(timesRDown, _T("右键按下次数:%d"), rButtonDownTimes);
InvalidateRect(hwnd, NULL, TRUE);
rButtonDownTimes++;
return 0;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
分别点击鼠标左键和右键能清楚的看到 局部变量 和全局变量的影响。
上述函数在鼠标点击的消息内,调用了 InvalidateRect(hwnd,NULL,TRUE)使得整个窗口无效,InvalidateRect函数会生成WM_PAINT消息。
关于第5章P107对 TextOut的使用
TextOut (hdc, 14*cxCaps+35*cxChar, cyChar*i, szBuffer,
wsprintf 函数的返回值就是字符串的长度。wsprintf (szBuffer, TEXT ("%5d"),GetDeviceCaps (hdc, devcaps[i].iIndex))) ;