ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

windows SDK编程简单总结

2022-02-05 18:34:50  阅读:189  来源: 互联网

标签:控件 窗口 windows 句柄 WM 编程 消息 DWORD SDK


CreateToolhelp32Snapshot

<TlHelp32.h>这个头文件,有CreateToolhelp32Snapshot这个api

这个api的第一个参数是个宏,有的可以查看的是所有进程,有的是查看该进程的所有模块。

HANDLE WINAPI CreateToolhelp32Snapshot( DWORD dwFlags, DWORD th32ProcessID );

第二个是Pid,如果填0就是所有的。

但注意 只是一瞬间的快照。

TH32CS_SNAPHEAPLIST

Includes the heap list of the specified process in the snapshot.

TH32CS_SNAPMODULE

Includes the module list of the specified process in the snapshot.

TH32CS_SNAPPROCESS

Includes the process list in the snapshot.

TH32CS_SNAPTHREAD

Includes the thread list in the snapshot.

然后这个api返回的是一个句柄。

HANDLE类型的,句柄类似指针,只有有句柄程序才能对这个进行操作。

PROCESSENTRY32等一众结构体

这个是配套着刚才CreateToolhelp32Snapshot来使用的。

还有Process32First和Process32Next,这个句柄指向一个链表。

上述两个api第一个参数就是哪个HANDLE,第二个参数就是结构体指针。

所以判断没了,那肯定就是什么时候这个结构体是null就没了。

这个结构体储存这找到的程序的一切。

typedef struct tagPROCESSENTRY32 {

  DWORD dwSize;

  DWORD cntUsage;

  DWORD th32ProcessID;

  ULONG_PTR th32DefaultHeapID;

  DWORD th32ModuleID;

  DWORD cntThreads;

  DWORD th32ParentProcessID;

  LONG  pcPriClassBase;

  DWORD dwFlags;

  TCHAR szExeFile[MAX_PATH];

} PROCESSENTRY32;

typedef PROCESSENTRY32 *PPROCESSENTRY32;

类似这个api,还有THREADENTRY32...只不过是线程了。

继续类推,因为CreateToolhelp32Snapshot还有看模块的功能

所以还有MODULEENTRY32...

还有...其实,因为哪个宏还有TH32CS_SNAPHEAPLIST...所以还有对应的堆栈结构体?(回头都试试)

Process32First/Process32Next等一众api

把第一个哪个句柄放进去,对应的结构体放进去,这里之所以说是对应,因为还有Thread32First...等一众api

CloseHandle

这个是用来关闭句柄的,句柄用了不关闭,可能会造成内存泄露。

ExitProcess

用来关闭自己进程的,但是关闭的时候想好,有的东西被这个关闭可能不会被析构,毕竟

FindWindow和FindWindowEx

这两个是用来找找窗口的,连子窗口也可以找到

FindWindowEx是比FindWindow多了两个参数。

FindWindow第一个参数是窗口类的名字,第二个是窗口的名字。

FindWindowEx多出来的前俩个是两个HWND类型的,是用来判断查找范围的。

第一个参数是从哪个主窗口来查找,第二个则是从哪个子窗口开始查找。如果是0,都遍历一遍。

TermniateProcess

第一个就是进程句柄hProcess,第二个是退出码。

这个只要有进程句柄就可以关闭别的程序,0就是关闭自己.

OpenProcess

OpenProcess 函数用来打开一个已存在的进程对象,并返回进程的句柄

要注意他和CreateProcess的区别,这个是打开一个已经存在的进程,返回进程句柄。

而CreateProcess则是直接打开。

这个是返回进程句柄的,而CreateProcess则是返回个BOOL 下面在更详细地介绍CreateProcess

有了进程句柄,就可以干别的了。

OpenCreateProcess有三个参数

HANDLE OpenProcess( DWORD dwDesiredAccess, // access flag BOOL bInheritHandle, // handle inheritance option DWORD dwProcessId // process identifier);

第一个是一个宏

可以用来确定打开进程的一些特权,比如PROCESS_ALL_ACCESSS,这个是最常用的

第二个是不是继承原来父窗口的句柄 TRUE或者FALSE 第三个就是PID,进程ID,是唯一标识程序的东西。注意他和进程句柄,各种句柄的区别!

OpenProcess

这个是用来打开进程的,

而且需要STARTUPINFO和PROCESS_INFOMATION这两个结构体

如果想要立刻显示打开的进程,需要改一些东西,比如si.wShowWindow=true...

BOOL CreateProcess(

LPCTSTR lpApplicationName, // name of executable module 

LPTSTR lpCommandLine, // command line string 

LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD 

LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD 

BOOL bInheritHandles, // handle inheritance option 

DWORD dwCreationFlags, // creation flags 

LPVOID lpEnvironment, // new environment block 

LPCTSTR lpCurrentDirectory, // current directory name 

LPSTARTUPINFO lpStartupInfo, // startup information 

LPPROCESS_INFORMATION lpProcessInformation // process information );

注意最后两个参数! 最后一个PROCESS_INFOMATION存储着PID..进程ID。。句柄什么的

聪明如我,肯定还有OpenThread....

PROCESS_INFOMATION是一个输出的结构体,所以放进去是空的,出来就是满的了。

ReadProcessMemory与WirteProcessMemory

ReadProcessMemory非常好用,是进行读取内容必备的API,

他有这么多参数,

第一个就是进程句柄,第二个是读取的基质(从哪儿开始读),第三个是读到哪

第四个是读多少,如果想遍历整个进程,由4kb物理页+进程的低2GB空间即可

4096byte为一个物理页,存进去。

比较的时候就用for循环比较,而且是一个字节一个字节的比对目标数。

pdw = (DWORD*)&arBytes[i];比如这样pdw就是一个指向DWORD的变量了,假如DWORD是待查找数据的类型。

然后在进行比较就行。然后找到就是dwBaseAddress+i就是地址了。因为是一个字节一个字节地比较。

与之相比下,WriteProcessMemory使用起来就简单的多。

WirteProcessMemory函数原型

第一个还是进程句柄,然后第二个是要写的地址,第三个是从哪里写入,第四个是写多少

LPVOID就是个void*而已,终归是个类型,你甚至可以用DWORD和int来代表地址,最后强转就行!

CreateThread

这是一个创建线程的API,多个线程可以提高程序所占用的时间片,可以使计算机运行计算该程序的时间变长。

线程同步是一大问题

以后应该会学习。但是感觉也应该不要太用

线程要注意有个线程ID和线程处理函数

还有个WiatForSingleObject和WaitForMutipObject...的使用

InterLockIncerment

这个是原子锁,保护临界资源只能被一个线程访问而且必须访问完才能结束

ProcessProc

与其他窗口处理函数一样,线程处理函数也是有固定的格式的。

DWORD CALLBACK ProcessProc(LPVOID lParam);这个就是线程处理函数

WndProc和WinMain

WinMain在win32的地位就相当于是main函数console中的地位。

类似int main的固定格式

WinMain作为回调函数也有其格式

他的格式是

Int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR lpcmdline,int){

...

}

他是windows窗口第一个执行的程序。

而WndProc也是一个回调函数,是窗口过程。

他也遵循着固定的格式供操作系统调用。

他的格式是

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){

Case-switch的一个巨大结构体

return DefWindowProc(...);//用来返回默认的窗口处理过程

}

要记住,每个窗口(广义的窗口)都对应着一个窗口处理函数。无论是对话框,子窗口,控件,都有。

有的系统已经封装好的类,同样也有,你知道了这些信息,发送,同样是合理的。

所有比如有的时候SendMessage给子窗口,让按钮,edit实现一些功能是正常的。

各种消息

WM_QUIT WM_CLOSE...我觉得查询msdn是好的,但是也要稍微记一下常见消息的内容.

WNDCLASS和RegisterClass

WNDCLASS是win32非常核心的一个结构体,也叫做窗口类,只有有了窗口类,并且注册了,即以及让操作系统仍到内核,才可以进行CreateWindow一系列操作。

WNDCLASS里面有着很多东西,比如决定着窗口处理函数。

设置完WNDCLASS所有的成员之后,再进行RegisterClass即可

CreateWindow和ShowWindow以及UpdateWindow

这三个是相辅相成的,CreateWindow后,进行ShowWindow(SW_SHOW)和UpdateWindow()来使窗口进入消息循环。

消息循环

核心是三个api+MSG结构体

MSG结构体用来存储消息的详细信息

Hwnd、LWparam message消息类型

代码实现就是while(GetMessage(&msg,NULL,0,0)){

//GetMessage后面三个参数是限制范围的,一般全填0即可。

然后TranslateMessage(&msg);//转译键盘消息的

DispatchMesaage(&msg);//分发 来调用回调函数

}

SetTimer

这是一个定时器消息

有四个参数

SetTimer(hWnd, IDT_TIMER, 100, NULL);

第一个参数就是给那个窗口设置这个定时器,第二个是ID,第三个是毫秒时间 第四个是如果想给这个玩意弄个定时器处理函数的话你就弄.

定时器发的消息是WM_TIMER。Wparam是定时器的ID

Win32的控件

一定要深刻理解,窗口就是控件->控件也是窗口->更是子窗口->每个窗口都有对应的窗口处理函数->系统封装好的也有.

Win32也可以实现可视化编程,但是需要基于Dialog对话框来实现。

如果不这样的话,那么只能进行创建了。用CreateWindow进行创建

窗口类填写系统已经搞好的类,还要填上对应的窗口类的风格以及对应窗口类(比如按钮 文本框的ID

这些所有的子窗口,或者说是控件。被进行操作的话会产生WM_COMMAND消息

低16就是哪个控件 高16位就是具体是进行了哪个操作.

被进行操作对每个类型的控件各不相同,对于按钮,可能就是下压,对于文本框,有可能是改变里面的内容。总之各不相同.

上面说到 win32也可以可视化编程,但是要是再对话框上添加。

而且可视化编程拖拽上去的控件也具备了更强的封装,比如原来CreateWindow创建的复选框,你点击他也不会选中,但是拖拽上去的就会。

虽然拖拽上去的控件有了更完善的封装,但是没办法直接获取控件的句柄了。

所以用GetDlgItem可以获取 还有SetDlgItemText....利用ID就可以进行操作了

同样的,消息还是那些,但是处理要放在对话框的窗口过程进行处理了。

如你所想,对话框的窗口处理函数也是回调函数,因此他要遵循一定的规则,但是基本和WndProc一样。

DialogBox和EndDialog

DialogBox就是进行打开模式对话框的一个API

第一个是实例句柄,第二个是ID(在Vs里面的),第三个是父窗口句柄,第四个是对话框处理函数。

这是一个阻塞函数,而非模式对话框就不是一个阻塞函数了.

对话框的窗口处理函数

和WndProc一样 但是返回类型不一样 WndProc返回是LRESULT 而这个返回的是BOOL

返回值决定是不是由默认的处理函数进行处理.一般返回假.

WM_INITDIALOG

对话框的初始化并不是WM_CREATE,而是这个玩意

HBITMAP、HICON

既然有句柄,说明已经扔到内存里面去供程序去使用了。所以位图什么的,也变成句柄,供程序去加载使用。

加载位图的的函数

HBITMAP hBitMap=LoadBitmap(hInstance,(LPCTSTR)用VS加载进来的ID);

注意,加载位图只可以是Static进行加载

如果是手动拖拽的文本框,那么它默认的属性是不能加载图片的。

所以要用GetWindowLong和SetWindowLong来进行操作。

GetWindowLong和SetWindowLong

这两个东西非常有用,第一参数是窗口句柄,第二个是宏。

第二个宏填不同的东西可以实现很多不同的功能。常见的就是给窗口加新风格

GetWindowLong 函数检索有关指定窗口的信息。 该函数还将指定偏移量处的 32 位(长)值检索到额外的窗口内存中。

LONG GetWindowLong(  HWND hWnd,  // 窗口句柄

  int nIndex  // 填特定的参数以获取改句柄的不同信息;

下面是第二个参数可以填的一些特定值

常用的就是GWL_STYLE,他会返回改窗体的风格,对于不知道风格来加风格非常有用。

例子:比如我想给一个static窗口类添加一个可以显示图片的风格,却又不想改变他原有的风格,这就十分必要需要GetWindowLong这个函数了

LONG nStyle = GetWindowLong(hWndBMP, GWL_STYLE);

GetWindowLong SetWindowLong很重要

GetWindowLOng  就是获取原有的窗口风格

然后不改变原有风格的条件下还能加载

SetWindowLong(hWndBMP, GWL_STYLE,nStyle|SS_BITMAP);

当然,这里用到了SetWindowLong,要和GetWindowLOng对应起来使用.

STM_SETIMAGE

这个是利用SendMessage专门发给static的消息,让他来加载图片的

Wparam写IMAGE_BITMAP就是加载位图,lParam填句柄!

SetWindowPos

SetWindowPos函数改变一个子窗口,弹出式窗口或顶层窗口的尺寸,位置和Z序。子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口。

常用的就是用它改置顶窗口

第一个参数就是hwnd,第二个参数可以填写以下宏

  • HWND_BOTTOM:值为1,将窗口置于Z序的底部。如果参数hWnd标识了一个顶层窗口,则窗口失去顶级位置,并且被置在其他窗口的底部。
  • HWND_NOTOPMOST:值为-2,将窗口置于所有非顶层窗口之上(即在所有顶层窗口之后)。如果窗口已经是非顶层窗口则该标志不起作用。
  • HWND_TOP:值为0,将窗口置于Z序的顶部。
  • HWND_TOPMOST:值为-1,将窗口置于所有非顶层窗口之上。即使窗口未被激活窗口也将保持顶级位置。

中间四个就是各种位置,边界。

最后一个是窗口的属性,比如不能移动。

SendDlgItemMessage一众API

SendMessage和GetDlgItem的结合,不必用中间量HWND来过度了

类似的还有

IsDlgButtonChecked(hDlg,ID)==GetDlgItem+SendMessage(hbutton,BM_GETCHECK,0,0),这个是用来检测是不是按钮被点击了,BST_CHECKED这是一个返回值,说明被点击了

BM_开头的一众消息

是ButtonMessage的缩写,是专门给按钮用的,

比如检测是不是被点击了,发送过去让其被点击

常见的BM_GETMESSAGE BM_SETMESSAGE 等等

LB_开头的一众消息

是专门类List列表框用的,

比如LB_ADDSTRING lParam是zero 而wParam就是加的字符串

简单MFC

所谓MFC,就是微软把一系列东西进行了一系列封装。

比如hInstance封装成了CWinApp这个类,我们使用的话要继承

再比如我们HWND他给封装成了CFrameWnd或者CWnd这个类

我们使用同样要继承。

但是,MFC省去了冗余的代码,而且利用面向对象的思想,以及消息映射机制

让我们不必使用代码量非常之大的switch-case结构了

并且,MFC还封装了按钮,编辑框,让他们变成类。

加上相应成员和成员函数,大大减少了代码量。

正常创建一个窗口非常的简单

首先,先继承WinApp那个类,

然后,覆写虚函数InitInstance

然后类似地,把CWinApp(hInstance)和CFrameWnd(HWND)关联起来

如何关联呢?

在覆写InitInstance函数的时候m_pmainWnd=new CHelloWnd();即可

然后m_pMainWnd->show.....一系列操作

这个时候调过了WNDCLASS 和注册窗口类

然后写以下CMyFrameWnd类的构造函数.

在这个构造函数里面要干什么呢?当然是创建窗口了!

直接用Create这个函数创建就行了,是MFC这个类里面的,第一个是类名,我们不填的话最后兜兜转转下MFC会自己给我们申请一个.

消息映射机制

MFC六大机制之一

可以减少大量的switch-case这种代码

一般是在继承的CFrameWnd哪个类里面先声明消息映射

DECLARE_MESSAGE_MAP()

然后BEGIN_MESSAGE_MAP()

这个是个带参宏,第一个参数是子类,第二个是父类.

中间填各种映射的消息

比如ON_WM_PAINT啦这种正常的消息

然后记得在添加了详细映射机制的程序

如果是命令消息,那就ON_COMMAND

最后END_MESSAGE_MAP()

       先讲下Windows消息的分类。Windows消息分为系统消息和用户自定义消息。Windows系统消息有三种:

       1.标准Windows消息。除WM_COMMAND外以WM_开头的消息是标准消息。例如,WM_CREATE、WM_CLOSE。

       2.命令消息。消息名为WM_COMMAND,消息中附带了标识符ID来区分是来自哪个菜单、工具栏按钮或加速键的消息。

       3.通知消息。通知消息一般由列表框等子窗口发送给父窗口,消息名也是WM_COMMAND,其中附带了控件通知码来区分控件。

       CWnd的派生类都可以接收到标准Windows消息、通知消息和命令消息。命令消息还可以由文档类等接收。

最后,每个消息所对应的消息映射各不相同,需要查询msdn,比较在win32中,WM_消息l和wparam里面所代表的东西也不同啦.

MFC还有一个更方便的功能就是它基本上把所有的的HWND控件什么的都变成了自己的类。

这样利用面向对象的思想十分方便。

CreateToolhelp32Snapshot(TH32CS_SNAPMODULE)

这是用来进行模块快照的,进程并不是独立运行的,需要一大堆模块进行支持。

这个可以用来获取模块,和获取的进程快照是一模一样的!

静态库Lib

静态库Lib没有入口函数,所以直接在里面写函数就行

注意C和Cpp的导入静态库的区别!

Cpp支持重名函数,所以导出的时候名字可就不是那样了!

引入动态和静态链接库

#pragma comment(lib,”xxx.lib”)

这是引入静态链接库。

动态库的话,需要先进行加载。比较是外部的东西

一个进程想使用任何外部的东西肯定先要进行加载进程序,才可以使用。

HMODULE hDll=LoadLibrary(“xx.dll”);

然后直接GetProcAddress(hModule,“function name”);就直接可以获得

FARPROC类型的东西 其实就是个函数指针

也是函数的地址!

标签:控件,窗口,windows,句柄,WM,编程,消息,DWORD,SDK
来源: https://blog.csdn.net/u013677637/article/details/122792160

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有