打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
dotnet-call-the-win32-API-to-create-a-window
userphoto

2013.01.28

关注
dotnet调用win32 API创建窗口
原文链接:http://mjxy.cn/a-dotnet-call-the-win32-API-to-create-a-window.aspx
标准的win32窗口程序
相信熟悉windows编程的朋友,对于使用win32 api开发窗口应用程序一定不陌生。 下面的程序是从资源文件中加载一个图片并显示在窗口中。
#include <windows.h>
#include "resource.h"
TCHAR szClassName[] = TEXT("WIN32TEST");
HBITMAP hBmp;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_NCHITTEST:
return HTCAPTION;
case WM_LBUTTONDOWN:
break;
case WM_PAINT:
hdc = BeginPaint (hWnd, &ps);
if (hBmp)
{
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm);
HDC memdc = CreateCompatibleDC(NULL);
HBITMAP h = (HBITMAP)SelectObject(memdc, hBmp);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, memdc, 0, 0, SRCCOPY);
SelectObject(memdc, h);
}
EndPaint (hWnd, &ps);
break;
case WM_KEYDOWN:
if (wParam != VK_ESCAPE)
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (0);
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR     lpCmdLine, int  nCmdShow)
{
WNDCLASS wc;
HWND hWnd;
MSG msg;
hBmp = ::LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2));
if (hBmp)
{
ZeroMemory(&wc, sizeof(wc));
wc.style         = CS_HREDRAW | CS_VREDRAW;
wc.lpszClassName = szClassName;
wc.lpfnWndProc   = (WNDPROC)WndProc;
wc.hInstance     = hInstance;
if (RegisterClass(&wc))
{
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm);
hWnd = CreateWindow(szClassName, NULL, WS_POPUP, 0, 0, bm.bmWidth, bm.bmHeight, NULL, NULL, hInstance, NULL);
if (hWnd)
{
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
}
}
return -1;
}
如何将上边这个程序改写成dotNET呢,只需要照猫画虎把这段代码转换成dotNET就可以了。
需要了解的知识点:
Win32中的名柄(如:HWND,HDC, HINSTANCE)等等在dotnet都用IntPtr来表示。
窗口回调函数
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 使用dotnet中的代理来解决
delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
需要事先声明的结构可以在www.pinvoke.net网站中查询一下,复制过来即可。
2. 我们用到的几个主要结构
Win32
dotNET
typedef struct tagBITMAP
{
LONG        bmType;
LONG        bmWidth;
LONG        bmHeight;
LONG        bmWidthBytes;
WORD        bmPlanes;
WORD        bmBitsPixel;
LPVOID      bmBits;
}
internal struct BITMAP
{
public int bmType;
public int bmWidth;
public int bmHeight;
public int bmWidthBytes;
public ushort bmPlanes;
public ushort bmBitsPixel;
public IntPtr bmBits;
}
typedef struct tagPAINTSTRUCT {
HDC         hdc;
BOOL        fErase;
RECT        rcPaint;
BOOL        fRestore;
BOOL        fIncUpdate;
BYTE        rgbReserved[32];
}
internal struct PAINTSTRUCT
{
public IntPtr hdc;
public bool fErase;
public UnsafeNativeMethods.RECT rcPaint;
public bool fRestore;
public bool fIncUpdate;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
public byte[] rgbReserved;
}
struct tagWNDCLASSEXW {
UINT        cbSize;
/* Win 3.x */
UINT        style;
WNDPROC     lpfnWndProc;
int         cbClsExtra;
int         cbWndExtra;
HINSTANCE   hInstance;
HICON       hIcon;
HCURSOR     hCursor;
HBRUSH      hbrBackground;
LPCWSTR     lpszMenuName;
LPCWSTR     lpszClassName;
/* Win 4.0 */
HICON       hIconSm;
}
internal struct WNDCLASSEX
{
public uint cbSize;
public uint style;
public UnsafeNativeMethods.WndProc lpfnWndProc;
public int cbClsExtra;
public int cbWndExtra;
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
public string lpszMenuName;
public string lpszClassName;
public IntPtr hIconSm;
}
3.在vs2008中创建 wpf 应用程序,然后将自动生成的代码都删除掉。
4. 新建一个类Win32Methods,将需要用的win32 API函数在此声明。
5. 新建类Win32IndotNET类,在此实现与上面列出标准win32的实现。
声明回调函数、名柄、图片的资源ID等等。
public class Win32IndotNET
{
//回调窗口
private Win32Methods.WndProc wndProcCallback;
private IntPtr hInst = IntPtr.Zero;
private int resID;
private IntPtr hBmp = IntPtr.Zero;
private Win32Methods.BITMAP bm;
}
在构造函数中初始化窗口回调。
public Win32IndotNET(Module module, int resID)
{
hInst = Marshal.GetHINSTANCE(module);
this.resID = resID;
this.wndProcCallback = new Win32Methods.WndProc(this.WindowProcedure);
}
创建窗口并显示
public void CreateWindow()
{
IntPtr hWnd;
hBmp = Win32Methods.LoadBitmap(hInst, new IntPtr(resID));
if (hBmp != IntPtr.Zero)
{
Win32Methods.WNDCLASSEX lpwcx = new Win32Methods.WNDCLASSEX();
lpwcx.cbSize = (uint)Marshal.SizeOf(typeof(Win32Methods.WNDCLASSEX));
lpwcx.cbClsExtra = 0;
lpwcx.cbWndExtra = 0;
lpwcx.hbrBackground = IntPtr.Zero;
lpwcx.hCursor = IntPtr.Zero;
lpwcx.hIcon = IntPtr.Zero;
lpwcx.hIconSm = IntPtr.Zero;
lpwcx.hInstance = hInst;
lpwcx.lpfnWndProc = this.wndProcCallback;
lpwcx.lpszClassName = "MyWin";
lpwcx.lpszMenuName = null;
lpwcx.style = 0;
if (Win32Methods.RegisterClassExW(ref lpwcx) != 0)
{
int cb = Marshal.SizeOf(typeof(Win32Methods.BITMAP));
IntPtr lpvObject = Marshal.AllocCoTaskMem(cb);
Win32Methods.GetObject(hBmp, cb, lpvObject);
bm = (Win32Methods.BITMAP)Marshal.PtrToStructure(lpvObject, typeof(Win32Methods.BITMAP));
Marshal.FreeCoTaskMem(lpvObject);
hWnd = Win32Methods.CreateWindowEx(0, "MyWin", "", Win32Methods.WS_POPUP, 0, 0, bm.bmWidth, bm.bmHeight, IntPtr.Zero, IntPtr.Zero, hInst, IntPtr.Zero);
if (hWnd != IntPtr.Zero)
{
Win32Methods.ShowWindow(hWnd, Win32Methods.SW_SHOW);
Thread thread = new Thread(new ThreadStart(this.ThreadMethod));
thread.IsBackground = true;
thread.Start();
}
}
}
}
消息循环
private void ThreadMethod()
{
MSG msg = new MSG();
while (Win32Methods.GetMessage(ref msg, IntPtr.Zero, 0, 0) > 0)
{
Win32Methods.TranslateMessage(ref msg);
Win32Methods.DispatchMessage(ref msg);
}
GC.KeepAlive(this);
}
窗口回调函数
在WM_PAINT消息中将图片绘制到窗口
ESC键即出处理
窗口拖动处理
private IntPtr WindowProcedure(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
switch (msg)
{
case Win32Methods.WM_PAINT:
{
Win32Methods.PAINTSTRUCT lpPaint = new Win32Methods.PAINTSTRUCT();
IntPtr hdc = Win32Methods.BeginPaint(hWnd, out lpPaint);
if (hBmp != IntPtr.Zero)
{
IntPtr ptr = Win32Methods.CreateCompatibleDC(hdc);
IntPtr hgdiobj = Win32Methods.SelectObject(ptr, this.hBmp);
Win32Methods.BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, ptr, 0, 0, Win32Methods.SRCCOPY);
Win32Methods.SelectObject(ptr, hgdiobj);
Win32Methods.DeleteDC(ptr);
}
Win32Methods.EndPaint(hWnd, ref lpPaint);
return IntPtr.Zero;
}
case Win32Methods.WM_NCHITTEST:
{
return new IntPtr(Win32Methods.HTCAPTION);
}
case Win32Methods.WM_KEYDOWN:
{
if (wParam.ToInt32() == 0x1B)
Win32Methods.PostQuitMessage(0);
}
break;
}
return Win32Methods.DefWindowProc(hWnd, msg, wParam, lParam);
}
6. 创建启动代码
static void Main(string[] args)
{
Win32IndotNET win32 = new Win32IndotNET(typeof(App).Module, 2008);
win32.CreateWindow();
new Application().Run();
}
7.创建资源文件
使用记事本创建 resource.rc文件,内容如下:
2008    BITMAP    "pic.bmp" (Pic.bmp 和 resource.rc 在同一目录)
在命令行窗口使用 rc 命令编译资源文件 生成 .res文件。
rc.exe resource.rc
右键单击项目属性在Resource File 中指定编译好的 res文件。
8. 生成并运行。
一般dotNET的程序运行时第一次加载的时候会很慢,所以可以利用win32api来制作启动屏幕是一个不错的选择。
程序代码下载
Win32dotNET.zip
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
跟我一起玩Win32开发(14):用对话框作为主窗口
2.Windows 界面技术发展现状
C语言+win32api写窗体应用程序
在.NET中基于Windows消息的IPC实现
Bezier曲线原理及实现代码(c++)
[VS2010]简易电子钢琴
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服