title: SDK编程一
date: 2019-10-18 17:35:09
tags: SDK
categroies: 编程
第一个windows窗口程序
创建一个窗口程序的空项目,或者创建一个控制台空项目,调整下面的选项:
#include <Windows.h>
int WINAPI WinMain(
HINSTANCE hInstance, //实例句柄
HINSTANCE hPreInstance, //没有用了
LPSTR szCmd, //命令行参数
int nShow //命令行参数
)
{
MessageBox(0, L"你好", L"友情提示", 0);
return 0;
}
在windows下编程,有两个问题需要提前了解:
1.在windows下,没有比较好用的输出数字的函数,我通常都需要自己转换:
int WINAPI WinMain(
HINSTANCE hInstance, //实例句柄
HINSTANCE hPreInstance, //没有用了
LPSTR szCmd, //命令行参数
int nShow //命令行参数
)
{
//想要将nNum的值,用MessageBox显示出来。
//数字转字符串
int nNum = 100;
char buf[100] = {};
sprintf_s(buf, "%d", nNum);
MessageBoxA(0, buf, "友情提示", 0);
return 0;
}
2.所有的字符串相关的API函数,都分成两个版本:A版和W版
int WINAPI WinMain(
HINSTANCE hInstance, //实例句柄
HINSTANCE hPreInstance, //没有用了
LPSTR szCmd, //命令行参数
int nShow //命令行参数
)
{
//想要将nNum的值,用MessageBox显示出来。
//数字转字符串
int nNum = 100;
char buf[100] = {};
wchar_t buf2[100] = {};
sprintf_s(buf, "%d", nNum);
swprintf_s(buf2, L"%d", nNum);
MessageBoxA(0, buf, "友情提示", 0);
MessageBoxW(0, buf2, L"友情提示", 0);
return 0;
}
由于在我们使用的时候会有中文的情况,所以一般我们都使用T版函数
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
int WINAPI WinMain(
HINSTANCE hInstance, //实例句柄
HINSTANCE hPreInstance, //没有用了
LPSTR szCmd, //命令行参数
int nShow //命令行参数
)
{
//想要将nNum的值,用MessageBox显示出来。
//数字转字符串
int nNum = 100;
char buf[100] = {};
wchar_t buf2[100] = {};
sprintf_s(buf, "%d", nNum);
swprintf_s(buf2, L"%d", nNum);
MessageBoxA(0, buf, "友情提示", 0);
MessageBoxW(0, buf2, L"友情提示", 0);
//t版函数
TCHAR buf3[100] = { _T("helloworld") };
_stprintf_s(buf3, _T("%d"), nNum);
MessageBox(0, buf3, _T("友情提示"), 0);
return 0;
}
asc
和unicode
之间的转换。
// 宽字符转换为多字符(Unicode --> ASCII)
#define WCHAR_TO_CHAR(lpW_Char, lpChar) \
WideCharToMultiByte(CP_ACP, NULL, lpW_Char, -1,
lpChar, _countof(lpChar), NULL, FALSE);
// 多字符转换为宽字符(ASCII --> Unicode)
#define CHAR_TO_WCHAR(lpChar, lpW_Char) \
MultiByteToWideChar(CP_ACP, NULL, lpChar, -1,
lpW_Char, _countof(lpW_Char));
在windows下输出调试信息:
bool _trace(const TCHAR *format, ...) //变参函数
{
TCHAR buffer[1000];
va_list argptr;
va_start(argptr, format);
//将格式化信息写入指定的缓冲区
wvsprintf(buffer, format, argptr);
va_end(argptr);
//将缓冲区信息输出
OutputDebugString(buffer);
return true;
}
int WINAPI WinMain(
HINSTANCE hInstance, //实例句柄
HINSTANCE hPreInstance, //没有用了
LPSTR szCmd, //命令行参数
int nShow //命令行参数
)
{
int nNum = 100;
_trace(_T("这个数字为%d"), nNum);
return 0;
}
我们也可以自己封装带格式控制符的Messagebox
bool _MyMessageBox(const TCHAR *format, ...) //变参函数
{
TCHAR buffer[1000];
va_list argptr;
va_start(argptr, format);
//将格式化信息写入指定的缓冲区
wvsprintf(buffer, format, argptr);
va_end(argptr);
//将缓冲区信息输出
MessageBox(0,buffer,_T("提示"),0);
return true;
}
int WINAPI WinMain(
HINSTANCE hInstance, //实例句柄
HINSTANCE hPreInstance, //没有用了
LPSTR szCmd, //命令行参数
int nShow //命令行参数
)
{
int nNum = 100;
_MyMessageBox(_T("这个数字为%d"), nNum);
return 0;
}
关于windows程序的错误码:
int WINAPI WinMain(
HINSTANCE hInstance, //实例句柄
HINSTANCE hPreInstance, //没有用了
LPSTR szCmd, //命令行参数
int nShow //命令行参数
)
{
HANDLE h = GetStdHandle(100);
int nError = GetLastError();//这个函数能够获取到最近一次调用的API的错误码
_MyMessageBox(_T("错误码为:%d"), nError);
return 0;
}
在调试的时候,快速监视到错误码的方法:
制作一个能够解析错误码的工具,能够提供出错的具体位置:
#define CHAR_TO_WCHAR(lpChar, lpW_Char) \
MultiByteToWideChar(CP_ACP, NULL, lpChar, -1, \
lpW_Char, _countof(lpW_Char));
void MyGetErrorInfo(
LPCTSTR lpErrInfo,
UINT unErrCode,
TCHAR* tFile,
UINT unLine) // unLine=__LINE__
{
LPTSTR lpMsgBuf = nullptr;
WCHAR szMessage[128] = { 0 };
WCHAR szCaption[128] = { 0 };
//这个函数能够将错误码解析为错误信息
FormatMessage(0x1300, NULL, unErrCode,
0x400, (LPTSTR)&lpMsgBuf, 64, NULL);
swprintf_s(szMessage, 128,
L"Error_0x%08X:%s", unErrCode, lpMsgBuf);
swprintf_s(szCaption, 128,
L"%s:%s:(Error Line:%05d)", lpErrInfo, tFile, unLine);
MessageBox(NULL, szCaption, szMessage , MB_OK);
}
int WINAPI WinMain(
HINSTANCE hInstance, //实例句柄
HINSTANCE hPreInstance, //没有用了
LPSTR szCmd, //命令行参数
int nShow //命令行参数
)
{
HANDLE h = GetStdHandle(100);
//1 获得错误码
int nError = GetLastError();
//2 得到出错的文件路径
wchar_t buf[100] = {};
CHAR_TO_WCHAR(__FILE__, buf);
//3 输出错误信息
MyGetErrorInfo(_T("十五派友情提示您:"), nError, buf,__LINE__-1);
return 0;
}
第一个窗口程序:
#include <Windows.h>
#include <tchar.h>
//int WinMain(
// HINSTANCE hInstance,
// HINSTANCE hPreInstance,
// LPSTR szCmd,
// int nShow
//);
//int wWinMain(
// HINSTANCE hInstance,
// HINSTANCE hPreInstance,
// LPWSTR szCmd,
// int nShow
//);
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
int WINAPI _tWinMain(
HINSTANCE hInstance,
HINSTANCE hPreInstance,
LPTSTR szCmd,
int nShow
)
{
//1 设计窗口类
//UINT style;
//WNDPROC lpfnWndProc;
//int cbClsExtra;
//int cbWndExtra;
//HINSTANCE hInstance;
//HICON hIcon;
//HCURSOR hCursor;
//HBRUSH hbrBackground;
//LPCWSTR lpszMenuName;
//LPCWSTR lpszClassName;
WNDCLASS wc;
wc.style = CS_VREDRAW | CS_HREDRAW;//类风格
wc.lpfnWndProc = WndProc;//回调函数的地址(重要)
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;//实例句柄,代表此程序
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"15PB";
//2 注册窗口类
RegisterClass(&wc);
//3 创建窗口
HWND hWnd = CreateWindow(
L"15PB", //类名
L"第一个窗口", //窗口名
WS_OVERLAPPEDWINDOW,//重叠窗口风格
100, 100, 400, 600, //位置和大小
NULL, //父窗口句柄
NULL, //菜单句柄
hInstance, //实例句柄
NULL //附加信息
);
//4 更新显示窗口
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
//5 实现消息循环
MSG msg = {};
// 5.1 获取消息
//GetMessage得到WM_QUIT消息的时候,会返回False
while (GetMessage(&msg, 0, 0, 0))
{
// 5.2 转换消息 将WM_KEYDOWN转换WM_CHAR
TranslateMessage(&msg);
// 5.3 派发消息
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(
HWND hWnd,
UINT uMessage,
WPARAM wParam,
LPARAM lParam
)
{
switch (uMessage)
{
case WM_CLOSE:
PostQuitMessage(0);//会发出一个WM_QUIT消息
break;
default:
break;
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
常见的消息处理:WM_CLOSE 窗口关闭的消息
WM_DESTORY 窗口销毁的消息
WM_KEYDOWN 键盘按下的消息
WM_CHAR 字符按键消息
WM_LBUTTONDOWN 鼠标左键单击消息
WM_MOVING 窗口移动消息
WM_SIZE 窗口大小改变的消息
需要用到的一个函数:GetClientRect 获取窗口的大小
LRESULT CALLBACK WndProc(
HWND hWnd,
UINT uMessage,
WPARAM wParam,
LPARAM lParam
)
{
switch (uMessage)
{
case WM_CREATE://一般进行一些初始化的操作
break;
case WM_DESTROY:
_trace(L"接到了wm_destory消息\n");
PostQuitMessage(0);//会发出一个WM_QUIT消息
break;
case WM_CLOSE:
_trace(L"接到了wm_close消息\n");
break;
case WM_KEYDOWN:
_trace(L"接到了wm_keydown消息\n");
_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);
break;
case WM_CHAR://可见字符
_trace(L"接到了wm_char消息\n");
_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);
break;
case WM_LBUTTONDOWN://鼠标左键单击
{
_trace(L"接到了wm_lbuttondown消息\n");
int x = LOWORD(lParam);
int y = HIWORD(lParam);
_trace(L"鼠标左键点击了x:%d,y:%d\n",x,y);
}
case WM_SIZE://窗口大小发生改变了
{
_trace(L"接到了wm_size消息\n");
RECT rc = {};
GetClientRect(hWnd,&rc);
_trace(L"鼠标左键点击了l:%d,r:%d,t:%d,b:%d\n",
rc.left, rc.right,rc.top, rc.bottom);
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
关于PostMessage,SendMessage,自定义消息
#define WM_MYMESSAGE WM_USER+2
LRESULT CALLBACK WndProc(
HWND hWnd,
UINT uMessage,
WPARAM wParam,
LPARAM lParam
)
{
switch (uMessage)
{
case WM_CREATE://一般进行一些初始化的操作
break;
case WM_DESTROY:
_trace(L"接到了wm_destory消息\n");
PostQuitMessage(0);//会发出一个WM_QUIT消息
break;
case WM_CLOSE:
_trace(L"接到了wm_close消息\n");
break;
case WM_KEYDOWN:
_trace(L"接到了wm_keydown消息\n");
_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);
break;
case WM_CHAR://可见字符
_trace(L"接到了wm_char消息\n");
_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);
break;
case WM_LBUTTONDOWN://鼠标左键单击
{
_trace(L"接到了wm_lbuttondown消息\n");
int x = LOWORD(lParam);
int y = HIWORD(lParam);
_trace(L"鼠标左键点击了x:%d,y:%d\n",x,y);
}
case WM_SIZE://窗口大小发生改变了
{
_trace(L"接到了wm_size消息\n");
RECT rc = {};
GetClientRect(hWnd,&rc);
_trace(L"鼠标左键点击了l:%d,r:%d,t:%d,b:%d\n",
rc.left, rc.right,rc.top, rc.bottom);
}
break;
case WM_MYMESSAGE:
{
_trace(L"接到了wm_mymessage消息\n");
_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);
MessageBox(0, 0, 0, 0);
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
消息泵处理消息
#define WM_MYMESSAGE WM_USER+2
int main()
{
//FindWindow
PostMessage(
(HWND)0x00360E7C,
WM_MYMESSAGE,
68, 55
);
}