学习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;
}

好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***