第一个windows程序
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
MessageBox(NULL, TEXT("hello world"), TEXT("hello"), 3 | MB_ICONINFORMATION);
return 0;
}
unicode编码问题
这个函数的TEXT是说明这个字符串使用unicode编码格式。本质上是一个宏,帮你添加了一个前缀L
MessageBox(NULL, TEXT("hello world"), TEXT("hello"), 3 | MB_ICONINFORMATION);
unicode是啥?
unicode统一使用两个字节来存放,英文也是两个字节,中文也是两个字节。将所有国家的字符都放进unicode里面
我们看一下源代码: 可以发现,TEXT其实是一个宏,作用就是把这个字符串前面添加一个L。
ps:如果要声明一个字符是使用unicode编码格式,必须这么写。类型是wchar_t, 字符前要加上一个L。
wchar_t ch = L'我';
于是乎,在预处理过后,上面那个MessageBox函数就变成了 这样就说明了使用了unicode字符集
MessageBox(NULL, L"hello world", L"hello", ...);
wchar_t TCHAR
在unicode编码下TCHAR就是wchar_t的别名,在其他编码格式下TCHAR就是char。
看源码:
因此我们使用TCHAR,那在不同编码的情况下,编译器会自动的帮你识别。
因此以后我们直接用TCHAR即可。
TCHAR* szContent = TEXT("HELLO WORLD");
static TCHAR szCaption[] = TEXT("hello");作者说不要让这个字符串在stack上
MessageBox(NULL, szContent, szCaption, 3 | MB_ICONINFORMATION);
创建窗口流程
代码:
#include<windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("AltWind");
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 require Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(
szAppName,
TEXT("Alternate and Winding Fill Modes"),
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 POINT aptFigure[10] = { 10, 70, 50, 70, 50, 10, 90, 10, 90, 50,
30, 50, 30, 90, 70, 90, 70, 30, 10, 30 };
static int cxClient, cyClient;
HDC hdc;
int i;
PAINTSTRUCT ps;
POINT apt[10];
switch (message)
{
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, GetStockObject(GRAY_BRUSH));
for (i = 0; i < 10; i++)
{
apt[i].x = cxClient * aptFigure[i].x / 200;
apt[i].y = cyClient * aptFigure[i].y / 100;
}
SetPolyFillMode(hdc, ALTERNATE);
Polygon(hdc, apt, 10);
for (i = 0; i < 10; i++)
{
apt[i].x += cxClient / 2;
}
SetPolyFillMode(hdc, WINDING);
Polygon(hdc, apt, 10);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
消息机制
其实就是生产者消费者模型,生产者是我们用户,做一些操作就是产生消息,queue就是系统的消息队列。消费者就是应用程序的消息队列,它们拿到消息之后自己去处理并返回结果。
WM_PAINT,WM_TIMER,WM_QUIT是三个特殊的消息,这三个消息会时刻放在消息队列的最后。
消息会会分为队列化消息和非队列化消息。非队列化消息就是可以插队的消息。
写回调的那个消息机制函数,就是写如何处理这些消息。
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
这些东西都是固定的
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
处理消息
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("hello world"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("被按了"), TEXT("安安安"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("被按了"), TEXT("安安安"), MB_YESNO) == IDYES)
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
默认的处理方法,,比如说这里我没有写VM_CREATE怎么处理,直接在这里返回了
return DefWindowProc(hwnd, message, wParam, lParam);
}
窗口退出流程
设备环境句柄
通过设备环境句柄hdc来在窗口画画。
获取环境句柄
方法1:
hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
方法2:
hdc = GetDC(hwnd);
ReleaseDC(hwnd, hdc);
文本输出
TextOut
TextOut(hdc, 100, 100, TEXT("hello world"), strlen("hello world"));
那个x和y是用来定位文本的位置的。
|