写这个博客的目的仅仅是为自己编程学习过程中作一些总结,时不时来回顾,里面也有没搞明白的,希望在今后积累够后,回来看看能够豁然开朗
1、消息及消息队列:操作系统是将感知到的事件传递给应用程序。
操作系统给出了消息结构体MSG: 和哪一个窗口相关,消息本身是什么,消息的附加参数是什么,消息发生投递的时间是什么,消息投递时当前光标的位置
typedef struct tagMSG {
HWND hwnd;
UINT message; //用一个整数标示一个消息,定义了宏用来表示数字,如按键消息,鼠标左键下按 WM_LBUTTONDOWN这个宏来表示数字就比较好记忆,
WPARAM wParam; //变量类型整数,指示消息的附加信息,具体的按键信息:如键盘按键的ASCIA码,获取具体字符
LPARAM lParam; <span style="font-family: Arial, Helvetica, sans-serif;">//变量类型整数,指示消息的附加信息</span>
DWORD time; //32位整数,doubleWord
POINT pt; // 当信息别投递时,当前光标的位置,
} MSG;
句柄(HANDLE),资源的标示,包括图标(HICON)、光标(HCurSOR)、窗口(HWND)、应用程序实例句柄(HINSTANCE)等
即给各种资源一个标示号,操作系统方便管理。
如HWND,是一个窗口句柄,操作系统通过这个句柄可以管理这个窗口的内容。操作系统是用句柄去索引的内存当中的资源。
2、每一个应用程序,操作系统都会为其建立一个消息队列,先进先出的缓冲区
3、Windows程序的入口函数
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance 应用程序实例句柄,代表
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line LP STR 指向字符串的指针
int nCmdShow // show state
);
4、窗口创建
a、设计一个窗口类;
b、注册窗口类;
c、创建窗口;
d、显示及更新窗口
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#pragma(lib, "MSVCRTD.lib");
LRESULT CALLBACK WinSunProc(HWND hwnd, //窗口句柄
UINT wMsg, //message identifier
WPARAM wParam, // first message parameter
LPARAM lParam); //second message parameter
int WINAPI WinMain(HINSTANCE hInstance, //应用程序实例句柄
HINSTANCE hPrevInstance, //先前应用程序的句柄
LPSTR lpCmdLine, //
int nCmdShow)
{
//设计一个窗口类
WNDCLASS wndcls;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndcls.hCursor = LoadCursor(NULL, IDC_CROSS);
wndcls.hIcon = LoadIcon(NULL,IDI_ERROR);
wndcls.hInstance = hInstance;
wndcls.lpfnWndProc = WinSunProc;
//代码在VC6中没问题. 因为它的代码没有按可编译为UNICODE版本的方式写,而VS2005之后版本默认是UNICODE编码的.所以所有使用到字串的地方都会出错.
//方法:修改VS2005之后版本的设置:选择你的项目->属性->常规->设置为不使用UNICODE,发现设置为多字节字符集也可以。发现用VS2005打开VC6的源代码,转换后是使用的多字节字符集。
// 在VS2008,vs2010中,项目->属性->常规->字符集:改为“使用多字节字符集”即可
//error C2440: “=”: 无法从“const char [11]”转换为“LPCWSTR”类问题
wndcls.lpszClassName = "tranning"; //wndClass.lpszClassName =L"DIRECTX11BookWindowClass";即在字符串的前面添加一个大写L。这样可以实现将字符串转换为宽字符集。
wndcls.lpszMenuName = NULL;
wndcls.style = CS_HREDRAW | CS_VREDRAW;
//注册窗口类
RegisterClass(&wndcls);
//创建一个窗口
HWND hwnd; //创建一个句柄,代表这窗口标识符 // DWORD dwStyle 窗口类型
hwnd = CreateWindow("tranning", "仿生机器人实验室",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); //消息转换,如将WM_KEYDOWN和WM_KEYUP转换成一个char 消息,并且投递到消息队列当中
DispatchMessage(&msg); //将收到的消息传递到窗口的回调函数,在窗口过程函数当中处理,理解为将消息送给操作系统再由操作系统去调用回调函数
}
return 0;
}
//窗口过程函数
//回调函数,
//CALLBACK 是标准调用约定_stdcall
LRESULT CALLBACK WinSunProc(HWND hwnd, //窗口句柄
UINT wMsg, //message identifier
WPARAM wParam, // first message parameter
LPARAM lParam) //second message parameter
{
switch(wMsg)
{
case WM_CHAR:
char szChar[20];
sprintf(szChar,"char is %d", wParam);
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd,"mouse clicked", "fangsheng",0);
HDC hdc; //device contacts , 提供这个接口,可以不用理会外设驱动怎么回事
hdc = GetDC(hwnd);
TextOut(hdc, 0, 50, "Windows程序设计基础", strlen("Windows程序设计基础"));
ReleaseDC(hwnd,hdc);
break;
case WM_PAINT: //窗口重绘函数
HDC hdc1;
PAINTSTRUCT ps;
hdc1 = BeginPaint(hwnd,&ps);
TextOut(hdc1, 0, 0, "程序设计基础", strlen("程序设计基础"));
EndPaint(hwnd, &ps);
break;
case WM_CLOSE:
if(IDYES == MessageBox(hwnd, "是否真的结束?","Windows程序设计基础",0))
{
DestroyWindow(hwnd); //销毁窗口
}
break;
case WM_DESTROY:
PostQuitMessage(0); // 投递一个WM_QUIT的消息到线程的消息队列当中,并且立即返回 终止消息发送,式消息循环终止,从而实现退出程序
break;
default:
return DefWindowProc(hwnd,wMsg,wParam,lParam); //其它消息由操作系统默认处理
}
return 0;
}
运行时遇到问题:
1、//error C2440: “=”: 无法从“const char [11]”转换为“LPCWSTR”类问题代码在VC6中没问题. 因为它的代码没有按可编译为UNICODE版本的方式写,而VS2005之后版本默认是UNICODE编码的.所以所有使用到字串的地方都会出错.
//方法:修改VS2005之后版本的设置:选择你的项目->属性->常规->设置为不使用UNICODE,发现设置为多字节字符集也可以。发现用VS2005打开VC6的源代码,转换后是使用的多字节字符集。// 在VS2008,vs2010中,项目->属性->常规->字符集:改为“使用多字节字符集”即可
2、MSVCRTD.lib(crtexe.obj) : error LNK2019: 无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用
在项目属性-连接器-系统- 子系统 , 将: /subsytem:console 改为/ subsystem:windows 至于为什么这么改,我就不是太清楚,
一开始在vs2010建立工程是默认控制台工程,我将里头main函数直接删除,并且输入以上代码,就出现这个问题。
_stdcall 与 cdcall 的区别
调用约定,一种是标准调用约定,一种是C语言的调用约定
定义的参数传递的顺序,还有堆栈清除有些差异
除了可变参数API 函数调用,其他都是_stdcall
VC++ 默认是cdcall,,在vc++调用_stdcall API函数时必须在声明函数时,加入_stdcall标示