win32 的DLL中創建windows窗口

   因工作需要,需要寫一個DLL,在DLL中創建windows窗口,網上有很多關於DLL創建窗口的文章,不過是基於MFC的, 卻鮮見直接用win32的DLL創建的。研究調試了一下,實現了在win32 DLL中創建窗口,集結成文,分享一下。

    實際上,用win32 DLL創建窗口有一個問題:

    1.CreateWindow用到的HINSTANCE從哪裏來?

      答:使用DllMain中的hModule

      BOOL APIENTRY DllMain(HANDLE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)

      hModule雖然是HANDLE,不能直接使用,強轉即可。

      g_hIntance= (HINSTANCE)hModule;

      Handle 是代表系統的內核對象,如文件句柄,線程句柄,進程句柄。

      HMODULE 是代表應用程序載入的模塊,win32系統下通常是被載入模塊的線性地址

      HINSTANCE 在win32下與HMODULE是相同的東西,在Win32下還存在主要是因爲win16。

      這是來自百度百科的解釋【1】。

      顯然HINSTANCE和HANDLE是兩個玩意,但這裏卻可以強轉,併成功了。調試過程中,看到的值

      hModule 是0x10000000

      g_hIntance是0x10000000,成員unused的值是9460301,

      顯然,hModule和g_hInstance 是模塊的起始地址。

      LoadLiibrary返回的HINSTANCE值也是模塊的起始地址。

      難道2者有什麼關聯?不細說了,有空研究。

 

    實際運行中,我是將win32 windows的模板代碼直接拷過來,直接白WinMain作爲一個函數給DLL調用了,但不完善,遇到以下問題:

    1. 編譯錯誤。一些宏沒有了,需要將resource.h、資源文件和一些資源如ico拷過來。

    2. 窗口顯示不了。跟了一下ShowWindow,發現返回值是0,表示窗口隱藏,原來是由nCmdShow決定的,由於沒有值,就全部給了NULL或0。給nCmdShow改成1之後就OK了。

    貼一下代碼:

    //dllmain

    // ad.cpp : 定義 DLL 應用程序的入口點。

#include "stdafx.h"

#include "ad.h"

#include "winform.h"

#include <process.h>

 

HINSTANCE g_hIntance;

int flag=0;

 

void c(void *)

{

flag=1;

MyCreateWindow(g_hIntance,NULL,NULL,1);

return;

}

 

BOOL APIENTRY DllMain( HANDLE hModule, 

                       DWORD  ul_reason_for_call, 

                       LPVOID lpReserved

)

{

g_hIntance= (HINSTANCE)hModule;

if(flag==0){

_beginthread(c,NULL,NULL);

flag=1;

}

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

case DLL_THREAD_ATTACH:

case DLL_THREAD_DETACH:

case DLL_PROCESS_DETACH:

break;

}

    return TRUE;

}

 

 

 

// 這是導出變量的一個示例

AD_API int nad=0;

 

// 這是導出函數的一個示例。

AD_API int fnad(void)

{

return 42;

}

 

// 這是已導出類的構造函數。

// 有關類定義的信息,請參閱 ad.h

Cad::Cad()

return; 

}

 

      //winform.h

      // ad.cpp : 定義應用程序的入口點。

//

 

#include "stdafx.h"

#include "resource.h"

#define MAX_LOADSTRING 100

 

// 全局變量:

HINSTANCE hInst; // 當前實例

TCHAR szTitle[MAX_LOADSTRING]; // 標題欄文本

TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口類名

 

BEGIN_OBJECT_MAP(ObjectMap)

END_OBJECT_MAP()

 

// 此代碼模塊中包含的函數的前向聲明:

ATOM MyRegisterClass(HINSTANCE hInstance);

BOOL InitInstance(HINSTANCE, int);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);

 

int APIENTRY MyCreateWindow(HINSTANCE hInstance,

                     HINSTANCE hPrevInstance,

                     LPTSTR    lpCmdLine,

                     int       nCmdShow)

{

  // TODO: 在此放置代碼。

MSG msg;

HACCEL hAccelTable;

 

// 初始化全局字符串

//LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

//LoadString(hInstance, IDC_AD, szWindowClass, MAX_LOADSTRING);

ATOM r=MyRegisterClass(hInstance);

 

// 執行應用程序初始化:

if (!InitInstance (hInstance, nCmdShow)) 

{

return FALSE;

}

 

hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_AD);

 

// 主消息循環:

while (GetMessage(&msg, NULL, 0, 0)) 

{

if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

 

return 0;

}

 

 

 

//

//  函數: MyRegisterClass()

//

//  目的: 註冊窗口類。

//

//  註釋: 

//

//    僅當希望在已添加到 Windows 95 的

//    “RegisterClassEx”函數之前此代碼與 Win32 系統兼容時,

//    才需要此函數及其用法。調用此函數

//    十分重要,這樣應用程序就可以獲得關聯的

//   “格式正確的”小圖標。

//

ATOM MyRegisterClass(HINSTANCE hInstance)

{

WNDCLASSEX wcex;

 

wcex.cbSize = sizeof(WNDCLASSEX); 

 

wcex.style = CS_HREDRAW | CS_VREDRAW;

wcex.lpfnWndProc = (WNDPROC)WndProc;

wcex.cbClsExtra = 0;

wcex.cbWndExtra = 0;

wcex.hInstance = hInstance;

wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_AD);

wcex.hCursor = LoadCursor(NULL, IDC_ARROW);

wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

wcex.lpszMenuName = (LPCTSTR)IDC_AD;

wcex.lpszClassName = _T("TEST");

wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

 

return RegisterClassEx(&wcex);

}

 

//

//   函數: InitInstance(HANDLE, int)

//

//   目的: 保存實例句柄並創建主窗口

//

//   註釋: 

//

//        在此函數中,我們在全局變量中保存實例句柄並

//        創建和顯示主程序窗口。

//

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)

{

   HWND hWnd;

 

   hInst = hInstance; // 將實例句柄存儲在全局變量中

 

   hWnd = CreateWindow(_T("TEST"), _T("TEST"), WS_OVERLAPPEDWINDOW,

      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

 

   if (!hWnd)

   {

 DWORD r=GetLastError();

           return FALSE;

   }

 

   BOOL r1=ShowWindow(hWnd, nCmdShow);

   //DWORD r=GetLastError();

   r1=UpdateWindow(hWnd);

   //r=GetLastError();

 

   return TRUE;

}

 

//

//  函數: WndProc(HWND, unsigned, WORD, LONG)

//

//  目的: 處理主窗口的消息。

//

//  WM_COMMAND - 處理應用程序菜單

//  WM_PAINT - 繪製主窗口

//  WM_DESTROY - 發送退出消息並返回

//

//

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

{

int wmId, wmEvent;

PAINTSTRUCT ps;

HDC hdc;

 

//*********************

 

//**********************

switch (message) 

{

case WM_COMMAND:

wmId    = LOWORD(wParam); 

wmEvent = HIWORD(wParam); 

// 分析菜單選擇:

switch (wmId)

{

case IDM_ABOUT:

DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);

break;

case IDM_EXIT:

DestroyWindow(hWnd);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

break;

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// TODO: 在此添加任意繪圖代碼...

EndPaint(hWnd, &ps);

break;

case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}

 

// “關於”框的消息處理程序。

LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

{

switch (message)

{

case WM_INITDIALOG:

return TRUE;

 

case WM_COMMAND:

if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 

{

EndDialog(hDlg, LOWORD(wParam));

return TRUE;

}

break;

}

return FALSE;

}

 

參考文獻:

1.HINSTANCE  http://baike.baidu.com/view/2434154.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章