1_windows历程.md
windows历程
Hello World
#include <windows.h>
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
MessageBox(NULL, TEXT("啦啦啦"), TEXT("Hello, World!"), MB_OKCANCEL);
return 0;
}
UNICODE
使用unicode解决ascii
DBCS编码集
使用TCHAR
作为字符集
窗口
/* -------------------------------------------------------------------
MyWindows.c -- 基本窗口模型
《Windows 程序设计(SDK)》视频教程
--------------------------------------------------------------------*/
#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("MyWindows");
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("这个程序需要在 Windows NT 才能执行!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName,
TEXT("鱼C工作室"),
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)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("大家好,这是我的第一个窗口程序!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); k
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
注意:使用MinGW编译时添加 -mwindows
选项
Windows 窗口的诞生过程。
定义窗口类结构(WNDCLASS) -> 注册窗口类(RegisterClass) -> 创建窗口(CreateWindow) -> 显示窗口(ShowWindow) -> 更新窗口(UpdateWindow) -> 消息循环(GetMessage -> TranslateMessage ->DispatchMessage)
事件驱动
DispatchMessage将消息传给os,os再调用callback
第001讲:【*】__stdcall,__cdecl,__pascal,__fastcall的区别
【*】标记为非必要掌握内容,可以先收藏,今后某一天你会需要用到的。
__cdecl
__cdecl 是 C Declaration 的缩写,表示 C 语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。
__stdcall
__stdcall 是 Standard Call 的缩写,是 C++ 的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是 this 指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retnX,X 表示参数占用的字节数,CPU 在 ret 之后自动弹出 X 个字节的堆栈空间,称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。
__pascal
__pascal 是 Pascal 语言(Delphi)的函数调用方式,也可以在 C/C++ 中使用,参数压栈顺序与前两者相反。返回时的清栈方式与 __stdcall 相同。
__fastcall
__fastcall 是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此 __fastcall 通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同,返回方式和 __stdcall 相当。
__thiscall
__thiscall 是为了解决类成员调用中 this 指针传递而规定的。__thiscall 要求把 this 指针放在特定寄存器中,该寄存器由编译器决定。VC 使用 ecx,Borland 的 C++ 编译器使用 eax。返回方式和 __stdcall 相当。
__fastcall 和 __thiscall 涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以 Windows 上的 COM 对象接口都定义为 __stdcall 调用方式。
C 语言中不加说明默认函数为 __cdecl 方式(C中也只能用这种方式),C++ 也一样,但是默认的调用方式可以在 IDE 环境中设置。
例子:test1(par1, par2, par3);
[扩展阅读] 第003讲:大写标识符的含义
在 Winodows 的定义中包含着许多大写标识符,这些标识符有很多都是以两个或三个字母作为前缀,且其后紧跟一个下划线:
CS_HREDRAW DT_VCENTER SND_FILENAME
CS_VREDRAW IDC_ARROW WM_CREATE
CW_USEDEFAULT IDI_APPLICATION WM_DESTROY
DT_CENTER MB_ICONERROR WM_PAINT
DT_SINGLELINE SND_ASYNC WS_OVERLAPPEDWINDOW
这些标识符其实都是宏定义,前缀标明该常量所属的一般类别,含义如下表:
前缀 | 含义 |
---|---|
CS | 类风格选项(ClassStyle) |
CW | 创建窗口选项(CreateWindow) |
DT | 文本绘制选项(DrawText) |
IDI | 图标的 ID 号(IDIcon) |
IDC | 光标的 ID 号(IDCursor) |
MB | 消息框选项(MessageBox) |
SND | 声音选项(Sound) |
WM | 窗口消息(WindowsMessage) |
WS | 窗口风格(WindowStyles) |
WM_PAINT,WM_TIMER , WM_QUIT 这三个消息属于特例,操作系统会把它们时刻放在消息队列的最后