helloworld

  1. #include<windows.h>
  2. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
  3. MessageBox(NULL, TEXT("这里是内容"), TEXT("这里是标题"), MB_OK);
  4. return 0;
  5. }

MessageBox 参数分别是:句柄、窗体内容、窗体标题、摁钮选项

  1. int MessageBox(
  2. HWND hWnd,
  3. LPCTSTR lpText,
  4. LPCTSTR lpCaption,
  5. UINT uType
  6. );
  1. MB_ABORTRETRYIGNORE about/retry/ignore
  2. MB_CANCELTRYCONTINUE cancel/retry/continue
  3. MB_HELP help
  4. MB_OK ok
  5. MB_OKCANCEL ok/cancel
  6. MB_RETRYCANCEL retry/cancel
  7. MB_YESNO yes/no
  8. MB_YESNOCANCEL yes/no/cancel

image.png

image.png

在 uType 那里可以加上一些图标

  1. MB_ICONEXCLAMATION 叹号警告
  2. MB_ICONWARNING 叹号警告
  3. MB_ICONINFORMATION i 标志
  4. MB_ICONASTERISK i 标志
  5. MB_ICONQUESTION 问号标志
  6. MB_ICONSTOP 红叉标志
  7. MB_ICONERROR 红叉标志
  8. MB_ICONHAND 红叉标志

image.png

可以通过这里设置默认按键(摁下回车选择的那个键)

  1. MB_DEFBUTTON1 指定第一个为默认按钮
  2. MB_DEFBUTTON2
  3. MB_DEFBUTTON3
  4. MB_DEFBUTTON4

创建窗口

  1. /* -------------------------------------------------------------------
  2. MyWindows.c -- 基本窗口模型
  3. 《Windows 程序设计(SDK)》视频教程
  4. 这段代码,先敲五遍再说
  5. --------------------------------------------------------------------*/
  6. #include <windows.h>
  7. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  8. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
  9. {
  10. static TCHAR szAppName[] = TEXT("MyWindows");
  11. HWND hwnd;
  12. MSG msg;
  13. WNDCLASS wndclass;
  14. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  15. wndclass.lpfnWndProc = WndProc;
  16. wndclass.cbClsExtra = 0;
  17. wndclass.cbWndExtra = 0;
  18. wndclass.hInstance = hInstance;
  19. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  20. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  21. wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  22. wndclass.lpszMenuName = NULL;
  23. wndclass.lpszClassName = szAppName;
  24. if (!RegisterClass(&wndclass))
  25. {
  26. MessageBox(NULL, TEXT("这个程序需要在 Windows NT 才能执行!"), szAppName, MB_ICONERROR);
  27. return 0;
  28. }
  29. hwnd = CreateWindow(szAppName,
  30. TEXT("鱼C工作室"),
  31. WS_OVERLAPPEDWINDOW,
  32. CW_USEDEFAULT,
  33. CW_USEDEFAULT,
  34. CW_USEDEFAULT,
  35. CW_USEDEFAULT,
  36. NULL,
  37. NULL,
  38. hInstance,
  39. NULL);
  40. ShowWindow(hwnd, iCmdShow);
  41. UpdateWindow(hwnd);
  42. while (GetMessage(&msg, NULL, 0, 0))
  43. {
  44. TranslateMessage(&msg);
  45. DispatchMessage(&msg);
  46. }
  47. return msg.wParam;
  48. }
  49. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  50. {
  51. HDC hdc;
  52. PAINTSTRUCT ps;
  53. RECT rect;
  54. switch (message)
  55. {
  56. case WM_PAINT:
  57. hdc = BeginPaint(hwnd, &ps);
  58. GetClientRect(hwnd, &rect);
  59. DrawText(hdc, TEXT("大家好,这是我的第一个窗口程序!"), -1, &rect,
  60. DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  61. EndPaint(hwnd, &ps);
  62. return 0;
  63. case WM_DESTROY:
  64. PostQuitMessage(0);
  65. return 0;
  66. }
  67. return DefWindowProc(hwnd, message, wParam, lParam);
  68. }

WNDCLASS 结构

  1. typedef struct tagWNDCLASSW {
  2. UINT style;
  3. WNDPROC lpfnWndProc;
  4. int cbClsExtra;
  5. int cbWndExtra;
  6. HINSTANCE hInstance;
  7. HICON hIcon;
  8. HCURSOR hCursor;
  9. HBRUSH hbrBackground;
  10. LPCWSTR lpszMenuName;
  11. LPCWSTR lpszClassName;
  12. } 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

  1. HWND WINAPI CreateWindow(
  2. _In_opt_ LPCTSTR lpClassName, // 窗口类名称
  3. _In_opt_ LPCTSTR lpWindowName, // 窗口标题
  4. _In_ DWORD dwStyle, // 窗口风格,或称窗口格式
  5. _In_ int x, // 初始 x 坐标
  6. _In_ int y, // 初始 y 坐标
  7. _In_ int nWidth, // 初始 x 方向尺寸
  8. _In_ int nHeight, // 初始 y 方向尺寸
  9. _In_opt_ HWND hWndParent, // 父窗口句柄
  10. _In_opt_ HMENU hMenu, // 窗口菜单句柄
  11. _In_opt_ HINSTANCE hInstance, // 程序实例句柄
  12. _In_opt_ LPVOID lpParam // 创建参数
  13. );

参数解析:

参数 含义
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

  1. hdc = GetDC(hwnd);
  2. ReleaseDC(hwnd, hdc);

上面获取句柄的方式是通用的,下面这种在响应 WM_PAINT 的时候使用

  1. hdc = BeginPaint(hwnd, &ps);
  2. EndPaint(hwnd, &ps);

DrawText

  1. int DrawText(
  2. _In_ HDC hDC, //设备环境句柄
  3. _Inout_ LPCTSTR lpchText, //指向将被写入的字符串的指针
  4. _In_ int nCount, //指向字符串中的字符数
  5. _Inout_ LPRECT lpRect, //指向 RECT 结构的指针
  6. _In_ UINT uFormat //指定格式化文本的方法
  7. );

RECT 结构定义了一个矩形的左上角和右下角的坐标
GetClientRect(hwnd, &rect); 获取窗口客户区的坐标 RECT 结构,用 DrawText 之前先用这个获取 RECT 结构

TextOut

  1. BOOL TextOut(
  2. _In_ HDC hdc, //设备环境句柄
  3. _In_ int nXStart, //x坐标
  4. _In_ int nYStart, //y坐标
  5. _In_ LPCTSTR lpString, //指向将被绘制字符串的指针
  6. _In_ int cchString //长度(多少个字符)
  7. );

StringCchPrintf

函数用于把数据格式化写入到指定的缓冲区里

  1. StringCchPrintf(szBuffer,128,TEXT("%d: %s"),i+1,TEXT("yichen"));
  2. HRESULT StringCchPrintf(
  3. _Out_ LPTSTR pszDest, //缓冲区
  4. _In_ size_t cchDest, //大小
  5. _In_ LPCTSTR pszFormat,//格式化字符串
  6. _In_ ... //格式化字符串的参数...
  7. );

StringCchLength

用来确定长度是否超过了规定的大小

  1. StringCchLength(szBuffer,12,&i_size);
  2. HRESULT StringCchLength(
  3. _In_ LPCTSTR psz, //缓冲区,待检查字符串
  4. _In_ size_t cchMax, //规定的大小
  5. _Out_ size_t *pcch //返回字符个数
  6. );

获取各种尺寸

文本尺寸

GetTextMetrics

将当前字体信息填充到指定的缓冲区

  1. BOOL GetTextMetrics(
  2. _In_ HDC hdc, //环境句柄
  3. _Out_ LPTEXTMETRIC lptm //指向 TEXTMETRIC 结构的指针
  4. );
  5. TEXTMETRICS tm;
  6. GetTextMetrics(hdc,&tm); //拿到之后就能用tm结构体中的值了
  7. cxChar = tm.tmAveCharWidth; //字符的宽度
  8. cyChar = tm.tmHeight + tm.tmExternalLeading; //字符的高度

TEXTMETRIC结构体
记录当前设备环境中有关字体的各种信息

窗口尺寸

GetSystemMetrics

  1. GetSystemMetrics(SM_CXSCREEN); //屏幕宽度
  2. GetSystemMetrics(SM_CYSCREEN); //屏幕高度
  3. //显示屏幕分辨率,单位是像素

客户区尺寸

LOWORD(lParam) 表示 x 轴
HIWORD(lParam) 表示 y 轴

添加滚动条

在 CreateWindow 的第三个参数加上 WS_VSCROLL(纵向滚动条)WS_HSCROLL(横向滚动条)

image.png