helloworld
#include<windows.h>int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {MessageBox(NULL, TEXT("这里是内容"), TEXT("这里是标题"), MB_OK);return 0;}
MessageBox 参数分别是:句柄、窗体内容、窗体标题、摁钮选项
int MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
MB_ABORTRETRYIGNORE about/retry/ignoreMB_CANCELTRYCONTINUE cancel/retry/continueMB_HELP helpMB_OK okMB_OKCANCEL ok/cancelMB_RETRYCANCEL retry/cancelMB_YESNO yes/noMB_YESNOCANCEL yes/no/cancel


在 uType 那里可以加上一些图标
MB_ICONEXCLAMATION 叹号警告MB_ICONWARNING 叹号警告MB_ICONINFORMATION 小 i 标志MB_ICONASTERISK 小 i 标志MB_ICONQUESTION 问号标志MB_ICONSTOP 红叉标志MB_ICONERROR 红叉标志MB_ICONHAND 红叉标志

可以通过这里设置默认按键(摁下回车选择的那个键)
MB_DEFBUTTON1 指定第一个为默认按钮MB_DEFBUTTON2MB_DEFBUTTON3MB_DEFBUTTON4
创建窗口
/* -------------------------------------------------------------------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);EndPaint(hwnd, &ps);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);}
WNDCLASS 结构
typedef struct tagWNDCLASSW {UINT style;WNDPROC lpfnWndProc;int cbClsExtra;int cbWndExtra;HINSTANCE hInstance;HICON hIcon;HCURSOR hCursor;HBRUSH hbrBackground;LPCWSTR lpszMenuName;LPCWSTR lpszClassName;} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;
成员解析:
| 成员 | 含义 |
|---|---|
| style | 指定窗口类型,各种“类风格”(详见下方↓)可以使用按位或操作符组合起来 |
| lpfnWndProc | 指定窗口过程(必须是回调函数) |
| cbClsExtra | 预留的额外空间,一般为 0 |
| cbWndExtra | 预留的额外空间,一般为 0 |
| hInstance | 应用程序的实例句柄 |
| hIcon | 为所有基于该窗口类的窗口设定一个图标 |
| hCursor | 为所有基于该窗口类的窗口设定一个鼠标指针 |
| hbrBackground | 指定窗口背景色 |
| lpszMenuName | 指定窗口菜单 |
| lpszClassName | 指定窗口类名 |
style 类风格解析
| 类风格 | 含义 |
|---|---|
| CS_VREDRAW | 移动或者调整窗口的高度(垂直方向)时,重绘整个窗口 |
| CS_HREDRAW | 移动或者调整窗口的宽度(水平方向)时,重绘整个窗口 |
| CS_DBLCLKS | 当用户光标在窗口内双击时,允许发送双击消息给窗口过程 |
| CS_OWNDC | 给予每个窗口实例分配一个唯一的 DC(注意,尽管这样是很方便,但它必须慎重使用,因为每个 DC 大约要占 800 个字节的内存) |
| CS_CLASSDC | 该窗口类的所有窗口实例都共享一个窗口类 DC |
| CS_PARENTDC | 1. 将子窗口的裁剪区域设置到父窗口的 DC 中去,这样子窗口便可以在父窗口上绘制自身。(注意,这是子窗口从系统缓存中获取 DC,而不是使用父窗口的 DC。) 2. 指定该风格可以提高系统性能 |
| CS_NOCLOSE | 禁止系统菜单的关闭选项 |
| CS_SAVEBITS | 1. 以位图形式保存被该窗口遮挡的屏幕部分,当给窗口移动以后,系统便可以用该保存的位图恢复屏幕移动的相应部分,从而系统不用向被该窗口遮挡的窗口发送 WM_PAINT 消息 2. 该特性对于菜单类型的窗口比较合适,因为它通常是简短的显示一下之后便消失 3. 设置该特性将增加显示该窗口的时间,因为它通常要先分配保存位图的内存 |
| CS_BYTEALIGNCLIENT | 在字节边界上(在 x 方向上)定位窗口的用户区域的位置 |
| CS_BYTEALIGNWINDOW | 在字节边界上(在 x 方向上)定位窗口的位置 |
| CS_GLOBALCLASS | 1. 当调用 CreateWindow 或 CreateWindowEx 函数来创建窗口时允许它的 hInstance 参数和注册窗口类时传递给 RegisterClass 的 hInstance 参数不同 2. 如果不指定该风格,则这两个 hInstance 必须相同 |
转载自:https://fishc.com.cn/thread-47123-1-1.html
CreateWindow
HWND WINAPI CreateWindow(_In_opt_ LPCTSTR lpClassName, // 窗口类名称_In_opt_ LPCTSTR lpWindowName, // 窗口标题_In_ DWORD dwStyle, // 窗口风格,或称窗口格式_In_ int x, // 初始 x 坐标_In_ int y, // 初始 y 坐标_In_ int nWidth, // 初始 x 方向尺寸_In_ int nHeight, // 初始 y 方向尺寸_In_opt_ HWND hWndParent, // 父窗口句柄_In_opt_ HMENU hMenu, // 窗口菜单句柄_In_opt_ HINSTANCE hInstance, // 程序实例句柄_In_opt_ LPVOID lpParam // 创建参数);
参数解析:
| 参数 | 含义 |
|---|---|
| lpClassName | 1. 窗口类名称,可以是一个指向 NULL 结束的字符串或一个整型数值 2. 如果是字符串,它指定了窗口的类名。这个类名可以是任何用函数 RegisterClass 注册的类名,或是任何预定义的控制类名 3. 如是一个整型量,它是由此前调用 theGlobalAddAtom 函数产生的全局量。这个小于 0xC000 的 16 位数必须是 lpClassName 参数字的低 16 位,该参数的高位必须是 0 |
| lpWindowName | 1. 窗口标题,一个指向 NULL 结束的字符串指针 2. 如果窗口风格指定了标题条,由 lpWindowName 指向的窗口标题将显示在标题条上 3. 当使用 Createwindow 函数来创建控制例如按钮,选择框和静态控制时,可使用 lpWindowName 来指定控制文本 |
| dwStyle | 指定创建窗口的风格(详见下方↓) |
| x | 1. 指定窗口的初始水平位置(x 坐标) 2. 对一个层叠或弹出式窗口,x 参数是屏幕坐标系的窗口的左上角的初始 x 坐标 3. 对于子窗口,x 是子窗口左上角相对父窗口客户区左上角的初始 x 坐标 4. 如果该参数被设为 CW_USEDEFAULT 则系统为窗口选择缺省的左上角坐标并忽略 y 参数,CW_USEDEFAULT 只对层叠窗口有效,如果为弹出式窗口或子窗口设定,则 x 和 y 参数被设为零。 |
| y | 1. 指定窗口的初始垂直位置(y 坐标) 2. 对一个层叠或弹出式窗口,y 参数是屏幕坐标系的窗口的左上角的初始 y 坐标 3. 对于子窗口,y 是子窗口左上角相对父窗口客户区左上角的初始 y 坐标 4. 对于列表框,y 是列表框客户区左上角相对父窗口客户区左上角的初始 y 坐标 5. 如果层叠窗口是使用 WS_VISIBLE 风格位创建的并且 x 参数被设为 CW_USEDEFAULT,则系统将忽略 y 参数 |
| nWidth | 1. 以设备单元指明窗口的宽度 2. 对于层叠窗口,nWidth 的值或是屏幕坐标的窗口宽度或是 CW_USEDEFAULT 3. 若 nWidth 是 CW_USEDEFAULT,则系统为窗口选择一个默认的高度和宽度(默认宽度为从初始 x 坐标开始到屏幕的右边界,缺省高度为从初始 y 坐标开始到目标区域的顶部。),CW_USEDEFAULT 只对层叠窗口有效,如果为弹出式窗口和子窗口设定 CW_USEDEFAULT 标志则 nWidth 和 nHeight 被设为零 |
| nHeight | 1. 以设备单元指明窗口的高度 2. 对于层叠窗口,nHeight 是屏幕坐标的窗口宽度 3. 若 nWidth 被设为 CW_USEDEFAULT,则系统忽略 nHeight 参数,自动为 nWidth 和 nHeight 设置默认参数 |
| hWndParent | 1. 指向被创建窗口的父窗口或所有者窗口的句柄 2. 若要创建一个子窗口或一个从属窗口,需提供一个有效的窗口句柄 3. 创建一个单纯的消息窗口,可以提供 HWND_MESSAGE 或提供一个己存在的消息窗口的句柄 |
| hMenu | 1. 指向窗口菜单句柄,或依据窗口风格指明一个子窗口标识 2. 对于层叠或弹出式窗口,hMenu 指定窗口使用的菜单:如果使用了菜单类,则 hMenu 可以为 NULL 3. 对于子窗口,hMenu 指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的 |
| hInstance | 与窗口相关联的模块实例的句柄 |
| lpParam | 1. 指向一个值的指针,该值传递给窗口 WM_CREATE 消息。该值通过在 IParam 参数中的 CREATESTRUCT 结构传递 2. 如果应用程序调用 CreateWindow 创建一个 MDI 客户窗口,则 lpParam 必须指向一个 CLIENTCREATESTRUCT 结构 |
dwStyle 窗口风格解析
| 窗口风格 | 含义 |
|---|---|
| WS_BORDER | 创建一个带边框的窗口 |
| WS_CAPTION | 创建一个有标题框的窗口(包含了 WS_BODER 风格) |
| WS_CHILD | 创建一个子窗口,这个风格的窗口不能拥有菜单也不能与 WS_POPUP 风格合用 |
| WS_CHILDWINDOW | 与 WS_CHILD 相同 |
| WS_CLIPCHILDREN | 当在父窗口内绘图时,排除子窗口区域,在创建父窗口时使用这个风格 |
| WS_CLIPSIBLINGS | 1. 排除子窗口之间的相对区域,也就是,当一个特定的窗口接收到 WM_PAINT 消息时,WS_CLIPSIBLINGS 风格将所有层叠窗口排除在绘图之外,只重绘指定的子窗口 2. 如果未指定该风格,并且子窗口是层叠的,则在重绘子窗口的客户区时,就会重绘邻近的子窗口 |
| WS_DISABLED | 1. 创建一个初始状态为禁止的子窗口,一个禁止状态的窗口不能接受来自用户的输入信息 2. 在窗口创建之后,可以调用 EnableWindow 函数来启用该窗口 |
| WS_DLGFRAME | 创建一个带对话框边框风格的窗口,这种风格的窗口不能带标题条 |
| WS_GROUP | 1. 指定一组“控制窗口”的第一个“控制窗口” 2. 这个“控制窗口”组由第一个“控制窗口”和随后定义的“控制窗口”组成,自第二个“控制窗口”开始每个“控制窗口”具有 WS_GROUP 风格 3. 每个组的第一个“控制窗口”带有 WS_TABSTOP 风格,从而使用户可以在组间移动 4. 用户随后可以使用光标在组内的控制间改变键盘焦点 |
| WS_HSCROLL | 创建一个有水平滚动条的窗口 |
| WS_ICONIC | 创建一个初始状态为最小化状态的窗口,与 WS_MINIMIZE 风格相同 |
| WS_MAXIMIZE | 创建一个初始状态为最大化状态的窗口 |
| WS_MAXIMIZEBOX | 创建一个具有最大化按钮的窗口,该风格不能与 WS_EX_CONTEXTHELP 风格同时出现,同时必须指定 WS_SYSMENU 风格 |
| WS_MINIMIZE | 创建一个初始状态为最小化状态的窗口,与 WS_ICONIC 风格相同 |
| WS_MINIMIZEBOX | 创建一个具有最小化按钮的窗口,该风格不能与 WS_EX_CONTEXTHELP 风格同时出现,同时必须指定 WS_SYSMENU 风格 |
| WS_OVERLAPPED | 产生一个层叠的窗口,一个层叠的窗口有一个标题条和一个边框,与 WS_TILED 风格相同 |
| WS_OVERLAPPEDWINDOW | 相当于(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX),与 WS_TILEDWINDOW 风格相同 |
| WS_POPUP | 创建一个弹出式窗口,该风格不能与 WS_CHILD 风格同时使用。 |
| WS_POPUPWINDOW | 相当于(WS_POPUP | WS_BORDER | WS_SYSMENU),但 WS_CAPTION 和 WS_POPUPWINDOW 必须同时设定才能使窗口某单可见 |
| WS_SIZEBOX | 创建一个可调边框的窗口,与 WS_THICKFRAME 风格相同 |
| WS_SYSMENU | 创建一个在标题条上带有窗口菜单的窗口,必须同时设定 WS_CAPTION 风格 |
| WS_TABSTOP | 1. 创建一个“控制窗口”,在用户按下 Tab 键时可以获得键盘焦点。 2. 按下 Tab 键后使键盘焦点转移到下一具有 WS_TABSTOP 风格的“控制窗口” |
| WS_THICKFRAME | 创建一个具有可调边框的窗口,与 WS_SIZEBOX 风格相同 |
| WS_TILED | 产生一个层叠的窗口,一个层叠的窗口有一个标题和一个边框,与 WS_OVERLAPPED 风格相同 |
| WS_TILEDWINDOW | 相当于(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX),与 WS_OVERLAPPEDWINDOW 风格相同 |
| WS_VISIBLE | 创建一个初始状态为可见的窗口 |
| WS_VSCROLL | 创建一个有垂直滚动条的窗口 |
转自:https://fishc.com.cn/thread-47139-1-1.html
消息机制
windows 是事件驱动、基于消息的操作系统
switch (message) 然后对各种消息进行处理
文本输出
设备环境句柄
一开始要获得设备环境句柄 hdc
hdc = GetDC(hwnd);ReleaseDC(hwnd, hdc);
上面获取句柄的方式是通用的,下面这种在响应 WM_PAINT 的时候使用
hdc = BeginPaint(hwnd, &ps);EndPaint(hwnd, &ps);
DrawText
int DrawText(_In_ HDC hDC, //设备环境句柄_Inout_ LPCTSTR lpchText, //指向将被写入的字符串的指针_In_ int nCount, //指向字符串中的字符数_Inout_ LPRECT lpRect, //指向 RECT 结构的指针_In_ UINT uFormat //指定格式化文本的方法);
RECT 结构定义了一个矩形的左上角和右下角的坐标GetClientRect(hwnd, &rect); 获取窗口客户区的坐标 RECT 结构,用 DrawText 之前先用这个获取 RECT 结构
TextOut
BOOL TextOut(_In_ HDC hdc, //设备环境句柄_In_ int nXStart, //x坐标_In_ int nYStart, //y坐标_In_ LPCTSTR lpString, //指向将被绘制字符串的指针_In_ int cchString //长度(多少个字符));
StringCchPrintf
函数用于把数据格式化写入到指定的缓冲区里
StringCchPrintf(szBuffer,128,TEXT("%d: %s"),i+1,TEXT("yichen"));HRESULT StringCchPrintf(_Out_ LPTSTR pszDest, //缓冲区_In_ size_t cchDest, //大小_In_ LPCTSTR pszFormat,//格式化字符串_In_ ... //格式化字符串的参数...);
StringCchLength
用来确定长度是否超过了规定的大小
StringCchLength(szBuffer,12,&i_size);HRESULT StringCchLength(_In_ LPCTSTR psz, //缓冲区,待检查字符串_In_ size_t cchMax, //规定的大小_Out_ size_t *pcch //返回字符个数);
获取各种尺寸
文本尺寸
GetTextMetrics
将当前字体信息填充到指定的缓冲区
BOOL GetTextMetrics(_In_ HDC hdc, //环境句柄_Out_ LPTEXTMETRIC lptm //指向 TEXTMETRIC 结构的指针);TEXTMETRICS tm;GetTextMetrics(hdc,&tm); //拿到之后就能用tm结构体中的值了cxChar = tm.tmAveCharWidth; //字符的宽度cyChar = tm.tmHeight + tm.tmExternalLeading; //字符的高度
TEXTMETRIC结构体
记录当前设备环境中有关字体的各种信息
窗口尺寸
GetSystemMetrics
GetSystemMetrics(SM_CXSCREEN); //屏幕宽度GetSystemMetrics(SM_CYSCREEN); //屏幕高度//显示屏幕分辨率,单位是像素
客户区尺寸
LOWORD(lParam) 表示 x 轴
HIWORD(lParam) 表示 y 轴
添加滚动条
在 CreateWindow 的第三个参数加上 WS_VSCROLL(纵向滚动条)WS_HSCROLL(横向滚动条)

