学习C 在windows下窗口应用程序开发笔记1
好文章,来自【福优学苑@音视频+流媒体】
简介
Windows下窗口的编程用的最多的就是C++,首先要理解windows程序的内部运行原理,上图:
Windows是通过消息循环机制(Message)来进行运行的,人与计算机之间交互的方式是通过操作系统,也就是说应用程序和输入输出设备之间交互的方式就是操作系统,媒介就类似于我们在写控制台程序时的函数调用机制一样,这里Windows封装好了许多,也就是Windows API。
入口函数
与控制台程序一样,在编写窗口程序时也需要有主函数,也就是入口函数,与控制台不同的是,这里的主函数格式如下:
int WINAPI WinMain(HINSTANCE hInstance, //当前句柄
HINSTANCE hPrevInstance, //上一个实例句柄
LPSTR lpCmdLine, //命令行参数
int nShowCmd); //显示窗口的情况
在MSDN中lpCmdLine的类型为LPWSTR,但是复制到程序中运行出错,原因是 WinMain函数的原始定义中lpCmdLine的类型是char *,但在中文系统的环境下因为启用了Unicode支持,LPTSTR代表的是WCHAR *。
创建一个完整的窗口程序需要四个步骤:
1.设计一个窗口类
2.注册窗口类
3.创建窗口
4.显示及更新窗口
学习第一天写的程序如下:
完整代码
#include <windows.h> #include <stdio.h> LRESULT CALLBACK WinSunProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //回调函数 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { WNDCLASS wndcls; //实例化 wndcls.cbClsExtra = 0; //额外的类的附加字节数 wndcls.cbWndExtra = 0; //窗口额外的附加字节数 wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //背景颜色,GetStockObject()函数的返回值是一个HGDIOBJ格式的,强制转换成HBRUSH格式的赋值 wndcls.hCursor = LoadCursor(NULL, IDC_CROSS); //光标的类型 wndcls.hIcon = LoadIcon(NULL, IDI_ERROR); //图标 wndcls.hInstance = hInstance; //应用程序的实例号 wndcls.lpfnWndProc = WinSunProc; //窗口过程函数 wndcls.lpszClassName = "热爱游戏"; //类名 wndcls.lpszMenuName = NULL; //菜单名 wndcls.style = CS_HREDRAW | CS_VREDRAW; //水平重画和垂直重画 RegisterClass(&wndcls); //注册窗口类 HWND hwnd; //实例化一个句柄 hwnd = CreateWindow("热爱游戏","我喜欢玩儿游戏!!!",WS_OVERLAPPEDWINDOW,0,0,600,400,NULL,NULL,hInstance,NULL); //建立一个窗口 ShowWindow(hwnd, SW_SHOWNORMAL); //显示窗口 UpdateWindow(hwnd); //更新窗口 MSG msg; //消息机制 while (GetMessage(&msg, NULL, 0, 0)) //消息循环 { TranslateMessage(&msg); //将传来的消息翻译 DispatchMessage(&msg); // } return 0; } LRESULT CALLBACK WinSunProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CHAR: char szChar[20]; sprintf_s(szChar,"char is %d",wParam); //sprintf_s和sprintf的区别 MessageBox(hwnd, szChar,"游戏",0); break; case WM_LBUTTONDOWN: MessageBox(hwnd,"mouse clicked","游戏",0); HDC hdc; hdc = GetDC(hwnd); TextOut(hdc, 0, 50, "我为游戏狂", strlen("我为游戏狂")); ReleaseDC(hwnd, hdc); break; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hwnd,&ps); TextOut(hDC,0,0,"我喜欢玩儿黑暗之魂3",strlen("我喜欢玩儿黑暗之魂3")); EndPaint(hwnd,&ps); break; case WM_CLOSE: if (IDYES==MessageBox(hwnd,"是否真的结束?","游戏",MB_YESNO)) { DestroyWindow(hwnd); //销毁窗口 } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; }
sprintf和sprintf_s的区别就在于安全性的问题, sprintf_s对于格式化string中的格式化的字符的有效性进行了检查,而sprintf仅仅检查格式化string或者缓冲区是否是空指针。如果有错误则返回相应的错误代码。
创建window窗口(自定义)
步骤:
1.注册窗口类
2.创建窗口
3.显示窗口
4.刷新窗口
5.消息处理函数
6.消息循环
#include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hParInstance, LPSTR lpCmdLine, int nCmd ) { //1.注册窗口类 WNDCLASSEXW wc; wc.cbSize = sizeof(WNDCLASSEX);//大小 wc.style = CS_HREDRAW | CS_VREDRAW;//样式 wc.lpfnWndProc = WndProc;//消息处理函数 wc.hInstance = hInstance; //实例句柄 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);//背景颜色 wc.cbClsExtra = 0;//类的额外信息 wc.cbWndExtra = 0;//窗口的额外信息 wc.lpszClassName = L"firstWindow";//类名(多用于区别公司) wc.lpszMenuName = NULL;//菜单名 wc.hCursor = LoadCursor(NULL, IDC_ARROW);//鼠标样式 默认 wc.hIcon = NULL;//图标 wc.hIconSm = NULL;//小图标 RegisterClassExW(&wc); //2.创建窗口 HWND hWnd = CreateWindowExW( NULL,//额外样式 wc.lpszClassName,//类名 L"我的第一个窗口",//窗口名字 WS_OVERLAPPEDWINDOW,//窗口样式 200, 100,//坐标 600, 600,//大小 NULL,//父窗口句柄 NULL,//菜单 wc.hInstance,//类的实例句柄 NULL//参数 ); if (!hWnd) { MessageBoxExW(NULL, L"未创建窗口", L"提示", MB_OK, 0); } //3.显示窗口 ShowWindow(hWnd, nCmd); //4.刷新窗口 UpdateWindow(hWnd); //6.消息循环 MSG msg; BOOL bRet; while (true) { if (PeekMessageW(&msg, nullptr, 0, 0, false)) { if ((bRet = GetMessage(&msg, nullptr, 0, 0)) != 0)//检测到窗口退出,返回0,不退出,返回非0 { if (bRet == -1) { //出现错误 } else { TranslateMessage(&msg);//翻译消息主要针对键盘 DispatchMessage(&msg);//派发消息 } } else { break; } } } return 0; } //5.消息处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY://销毁窗口 { PostQuitMessage(0);//退出程序 break; } default: return DefWindowProc(hWnd, message, wParam, lParam); } return NULL; }
好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***