dotNET中调用win32 API

 

1.    标准的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);

需要事先声明的结构可以在 http://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 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 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来制作启动屏幕是一个不错的选择。

 

http://files.cnblogs.com/coogle/Win32dotNET.rar

转载于:https://www.cnblogs.com/coogle/archive/2008/07/23/1249146.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值