关于DLL中创建窗口

dungeonsnd 2009-08-18 11:56:48

我现在要把窗口的创建及窗口过程封装到DLL里,主程序调用这个DLL里的函数后创建(多个)相互独立的子窗口。

最初,我在DLL里用全局函数创建窗口。然后,写了一个WIN32的测试程序来调用这个DLL,DLL创建子窗口成功,并且子窗口可以响应消息;但是在MFC的测试程序里调用同样的DLL时,创建子窗口成功,但是子窗口不能响应消息,也就是单击子窗口后,DLL中子窗口过程中的 case WM_LBUTTONDOWN没有执行(消息进不到子窗口的窗口过程中)。

后来,查到了Thunk技术。 想上面那个问题可能是由于MFC下调用DLL时,DLL创建子窗口的窗口过程没有得到正确句柄.(但是还是没搞明白,为什么同样的DLL,在WIN32下测试时,DLL创建的子窗口可以响应消息)。
我试着用Thunk技术,并用类来重写这个DLL。发现越写越复杂,要解决很多问题。比如,DLL及调用它的EXE程序之间共享 EXE中创建的DLL对象的指针。。等等。。 反正用Thunk时,遇到了很多问题。

再后来,发现ATL中用了Thunk技术,并封装了窗口。 但是我没有研究过ATL。 所以不知道它对我的目标有没有帮助。

请问,,我的目标是,让这个DLL 更面向对象,更易于维护,更易于调用者对子窗口的创建及销毁,,我要实现的这个DLL用哪个思路来做更好,? 谢谢!

比如,
1.在DLL中用全局函数(这个当然不是面向对象的,不容易维护,我不打算使用这种方法,而且调用者不能创建多个实例)
2.在DLL中用类来实现,自己封装窗口及窗口过程,运用Thunk技术来解决DLL中的窗口过程的句柄问题。(必须用Thunk或类似技术,因为窗口过程必须为全局的(或静态的) )
3.好好研究ATL(尚不知道ATL创建的DLL对我的要求是否有帮助),并用它来创建我的DLL。然后供MFC程序及WIN32程序来调用。


请帮我想个思路。谢谢!
急切,再次感谢!
...全文
915 28 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
dungeonsnd 2010-01-31
  • 打赏
  • 举报
回复
自己已解决,
dungeonsnd@126.com

结账!
cyofworld 2009-09-02
  • 打赏
  • 举报
回复
c/c++ code, vs2008 + win xp sp2, 使用多字节



// Test.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "Test.h"

#define MAX_LOADSTRING 100

HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名


ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);


//////////////////////////////////////////////////////////////////////////
class ZWindow;
ZWindow* g_pWnd = NULL;

#pragma pack(push,1)
struct _WndProcThunk
{
DWORD m_mov; // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
DWORD m_this;
BYTE m_jmp; // jmp WndProc
DWORD m_relproc; // relative jmp
};
#pragma pack(pop)

class WndProcThunk
{
public:
_WndProcThunk thunk;

void Init(WNDPROC proc, void* pThis)
{
thunk.m_mov = 0x042444C7; //C7 44 24 04
thunk.m_this = (DWORD)pThis;
thunk.m_jmp = 0xe9;
thunk.m_relproc = (int)proc - ((int)this+sizeof(_WndProcThunk));

::FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));
}
};

class ZWindow
{
public:

virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return FALSE;
}

HWND m_hWnd;
WndProcThunk m_thunk;

ZWindow(HWND hWnd = 0) : m_hWnd(hWnd) { }

inline void Attach(HWND hWnd)
{ m_hWnd = hWnd; }

inline BOOL ShowWindow(int nCmdShow)
{ return ::ShowWindow(m_hWnd, nCmdShow); }

inline BOOL UpdateWindow()
{ return ::UpdateWindow(m_hWnd); }

inline HDC BeginPaint(LPPAINTSTRUCT ps)
{ return ::BeginPaint(m_hWnd, ps); }

inline BOOL EndPaint(LPPAINTSTRUCT ps)
{ return ::EndPaint(m_hWnd, ps); }

inline BOOL GetClientRect(LPRECT rect)
{ return ::GetClientRect(m_hWnd, rect); }

BOOL Create(LPCTSTR szClassName, LPCTSTR szTitle, HINSTANCE hInstance, HWND hWndParent = 0,
DWORD dwStyle = WS_OVERLAPPEDWINDOW, DWORD dwExStyle = 0, HMENU hMenu = 0,
int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int nWidth = CW_USEDEFAULT, int nHeight = CW_USEDEFAULT)
{
m_hWnd = ::CreateWindowEx(dwExStyle, szClassName, szTitle, dwStyle, x, y,
nWidth, nHeight, hWndParent, hMenu, hInstance, NULL);

return m_hWnd != NULL;
}

static LRESULT CALLBACK StartWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ZWindow* pThis = g_pWnd;
pThis->m_hWnd = hWnd;

// initilize the thunk code
pThis->m_thunk.Init(WindowProc, pThis);

// get the address of thunk code
WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);

::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);

return pProc(hWnd, uMsg, wParam, lParam);
}

static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ZWindow* pThis = (ZWindow*)hWnd;

if (!pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam))
return ::DefWindowProc(pThis->m_hWnd, uMsg, wParam, lParam);
else
return 0;
}
};


class ZDriveWindow1 : public ZWindow
{
public:
virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

LRESULT OnPaint(WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;

hDC = BeginPaint(&ps);
GetClientRect(&rect);
::SetBkMode(hDC, TRANSPARENT);
::DrawText(hDC, "ZDriveWindow1", -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
EndPaint(&ps);

return 0;
}

LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
::MessageBox(NULL, "ZDriveWindow1::OnLButtonDown", "Msg", MB_OK);
return 0;
}
};

class ZDriveWindow2 : public ZWindow
{
public:
virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnPaint(WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;

hDC = BeginPaint(&ps);
GetClientRect(&rect);
::SetBkMode(hDC, TRANSPARENT);
::Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom);
::DrawText(hDC, "ZDriveWindow2", -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
EndPaint(&ps);

return 0;
}

LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
::MessageBox(NULL, "ZDriveWindow2::OnLButtonDown", "Msg", MB_OK);
return 0;
}

};

class ZDriveWindow3 : public ZWindow
{
public:
virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnPaint(WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;

hDC = BeginPaint(&ps);
GetClientRect(&rect);
::SetBkMode(hDC, TRANSPARENT);
::Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom);
::DrawText(hDC, "ZDriveWindow3", -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
EndPaint(&ps);

return 0;
}

LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
::MessageBox(NULL, "ZDriveWindow3::OnLButtonDown", "Msg", MB_OK);
return 0;
}

};

BOOL ZDriveWindow1::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{

if (uMsg == WM_NCDESTROY)
::PostQuitMessage(0);

switch (uMsg)
{
case WM_LBUTTONDOWN:
OnLButtonDown(wParam, lParam);
break;

case WM_PAINT:
OnPaint(wParam, lParam);
break;
}

return FALSE;
}

BOOL ZDriveWindow2::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_LBUTTONDOWN:
OnLButtonDown(wParam, lParam);
break;

case WM_PAINT:
OnPaint(wParam, lParam);
break;
}

return FALSE;
}


BOOL ZDriveWindow3::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_LBUTTONDOWN:
OnLButtonDown(wParam, lParam);
break;

case WM_PAINT:
OnPaint(wParam, lParam);
break;
}

return FALSE;
}
//////////////////////////////////////////////////////////////////////////



int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;

// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TEST, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST));

// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return (int) msg.wParam;
}




ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TEST);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);
}


BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

hInst = hInstance; // 将实例句柄存储在全局变量中

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);


char szAppName[] = "Hello world";
WNDCLASS wnd;
// ZDriveWindow1 zwnd1;
ZDriveWindow2 zwnd2;
ZDriveWindow3 zwnd3;

wnd.cbClsExtra = NULL;
wnd.cbWndExtra = NULL;
wnd.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wnd.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wnd.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
wnd.hInstance = hInstance;
wnd.lpfnWndProc = ZWindow::StartWndProc;
wnd.lpszClassName = szAppName;
wnd.lpszMenuName = NULL;
wnd.style = CS_HREDRAW | CS_VREDRAW;

if (!RegisterClass(&wnd))
{
::MessageBox(NULL, "Can not register window class", "Error", MB_OK | MB_ICONINFORMATION);
return -1;
}


g_pWnd = &zwnd2;
zwnd2.Create(szAppName, "Test", hInstance, hWnd,
WS_VISIBLE | WS_CHILD | ES_MULTILINE|WS_BORDER|WS_THICKFRAME|WS_OVERLAPPEDWINDOW, NULL, NULL, 20, 20, 150, 150);
zwnd2.ShowWindow(nCmdShow);

g_pWnd = &zwnd3;
zwnd3.Create(szAppName, "Test", hInstance, hWnd,
WS_VISIBLE | WS_CHILD | ES_MULTILINE|WS_BORDER|WS_THICKFRAME|WS_OVERLAPPEDWINDOW, NULL, NULL, 520, 20, 150, 150);
zwnd3.ShowWindow(nCmdShow);

return TRUE;
}


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, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, 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;
}


INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
return (INT_PTR)FALSE;
}
cyofworld 2009-09-02
  • 打赏
  • 举报
回复
顶一个,
期待高手解决!
dungeonsnd 2009-09-02
  • 打赏
  • 举报
回复
我把代码贴出来,谁能帮帮我,万分感谢!
下面是有问题的代码,单步过了,也用spy++看过了。
我不知道怎么解决。
dungeonsnd 2009-09-01
  • 打赏
  • 举报
回复
郁闷啊, 利用Thunk,编译出问题。。。 郁闷至极。。。
vincent_1011 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 dungeonsnd 的回复:]
引用 15 楼 vincent_1011 的回复:
要不你的dll接管主窗口的消息循环吧
setwindowlong


不可以哦。 因为我把这个DLL发布出去之后 用户调用了,如果我接管消息循环,那么主窗口岂不口执行不了自己的消息循环了,。。。比如它想关闭程序 有可能都关闭不了了,,除非子窗口再向主窗口发送消息,那样有点南辕北辙了。。。
消息还是应该主窗口收到,发送对应的子窗口,给相应的窗口过程处理比较妥当。
[/Quote]

我晕,你没搞过子类化吗?我说的接管只是为了在中间截获这个消息,然后还要给回主窗口的
关键字:CallWindowProc
dungeonsnd 2009-08-21
  • 打赏
  • 举报
回复
感谢上面的朋友回复,请下面的继续讨论,谢谢!
dungeonsnd 2009-08-21
  • 打赏
  • 举报
回复
UP...
dungeonsnd 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 vincent_1011 的回复:]
要不你的dll接管主窗口的消息循环吧
setwindowlong
[/Quote]

不可以哦。 因为我把这个DLL发布出去之后 用户调用了,如果我接管消息循环,那么主窗口岂不口执行不了自己的消息循环了,。。。比如它想关闭程序 有可能都关闭不了了,,除非子窗口再向主窗口发送消息,那样有点南辕北辙了。。。
消息还是应该主窗口收到,发送对应的子窗口,给相应的窗口过程处理比较妥当。
dungeonsnd 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 vincent_1011 的回复:]
引用 21 楼 dungeonsnd 的回复:
感谢!

我没听说过thunk技术,哈哈
[/Quote]

thunk是一组动态生成的ASM指令,它记录了窗口类对象的this指针,并且这组指令可以当作函数,既也可以是窗口过程来使用。thunk先把窗口对象this指针记录下来,然后转向到静态stdProc回调函数,转向之前先记录HWND,然后把堆栈里HWND的内容替换为this指针,这样在stdProc里就可以从HWND取回对象指针,定位到WindowProc了。
From:
http://hi.baidu.com/sdhexu/blog/item/33e5a5dde9321fee76c63891.html


根据我目前所所知(其它的方法还有待去学习,去研究!不过,肯定有!),对于封装窗口,貌似它是解决窗口过程函数与窗口句柄联系的最好的手段了。
vincent_1011 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 dungeonsnd 的回复:]
感谢!
[/Quote]
我没听说过thunk技术,哈哈
dungeonsnd 2009-08-21
  • 打赏
  • 举报
回复
感谢!
dungeonsnd 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 vincent_1011 的回复:]
引用 16 楼 dungeonsnd 的回复:
引用 15 楼 vincent_1011 的回复:
要不你的dll接管主窗口的消息循环吧
setwindowlong


不可以哦。 因为我把这个DLL发布出去之后 用户调用了,如果我接管消息循环,那么主窗口岂不口执行不了自己的消息循环了,。。。比如它想关闭程序 有可能都关闭不了了,,除非子窗口再向主窗口发送消息,那样有点南辕北辙了。。。
消息还是应该主窗口收到,发送对应的子窗口,给相应的窗口过程处理比较妥当。


我晕,你没搞过子类化吗?我说的接管只是为了在中间截获这个消息,然后还要给回主窗口的
关键字:CallWindowProc
[/Quote]

谢谢回复!


呵呵。。 没听过子类化这个名字,刚才查了一下,原来就是重定向消息。
其实我最近研究的Thunk技术跟你说的子类化有点类似哦(也许可以说成重定向),不知是否。
请看,这是在DLL中实现的


static LRESULT CALLBACK StartWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ZWindow* pThis = g_pWnd;
pThis->m_hWnd = hWnd;

// initilize the thunk code
pThis->m_thunk.Init(WindowProc, pThis);

// get the address of thunk code
WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);

::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);

return pProc(hWnd, uMsg, wParam, lParam);
}

static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ZWindow* pThis = (ZWindow*)hWnd;

if (!pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam))
return ::DefWindowProc(pThis->m_hWnd, uMsg, wParam, lParam);
else
return 0;
}

代码中把
把实例的地址传过来之后,利用Thunk技术把 HWND精巧地换成this指针(因为子窗口的HWND应该和相应的派生类关联起来,否则前者没办法处理自己窗口的消息),接着,在初始化thunk代码之后,获得thunk的地址并向thunk代码设置新的回调函数(::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);)。 然后,thunk代码会调用WindowProc,但是现在第一个参数就不是HWND了,事实上它是this指针。
vincent_1011 2009-08-20
  • 打赏
  • 举报
回复
要不你的dll接管主窗口的消息循环吧
setwindowlong
dungeonsnd 2009-08-20
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 fishion 的回复:]
C/C++ code#include<windows.h>
#include<commctrl.h>
#include<wchar.h>
#include<string.h>
#include"Resource.h"#define PROCRUNDLGAPI extern "C" __declspec(dllexport)
#include"ProcRunDlg.h"#define WM_STOPPROCTHREAD WM_USER + 102

HINSTANCE g_hinst= NULL;
HWND g_hwndDLG= NULL;
HWND g_TempDLG= NULL;
HBRUSH g_hbrBackground;
DWORD g_hThreadListId=0;int g_ListIndex=0;struct HookProcInfo{

TCHAR Operation[20];
TCHAR ProcessInfo[MAX_PATH];
};#define WM_STOPTHREAD WM_USER + 101

..........
[/Quote]

兄弟,你这个 CreateDialog(g_hinst,MAKEINTRESOURCE(IDD_RECORDLISTBOX),NULL,ReList_DlgProc);
。。
你自己没有封装窗口呀。你是使用资源的呀,当然可以响应消息了。 使用VC生成新建一个对话框资料载到DLL里可以直接用了。
我觉得,,微软在CreateDialog后已经把窗口的创建到消息的传递给封装得非常完美了(比如 createwindow(_T("button"),... ) ),你创建一个按钮,当然可以接收消息了,不用自己来理会消息接收正确与否。

我现在在DLL里用最原始的API创建窗口 CreateWindow();(而不要加载资源,因为我要在CreateWindow里根据调用者传到DLL里的参数来创建个性窗口)。 所以不可以加载资源的,而且我要在创建的子窗口里渲染图形,使用资源不太好用。
fishion 2009-08-20
  • 打赏
  • 举报
回复
#include <windows.h>
#include <commctrl.h>
#include <wchar.h>
#include <string.h>
#include "Resource.h"

#define PROCRUNDLGAPI extern "C" __declspec(dllexport)
#include "ProcRunDlg.h"

#define WM_STOPPROCTHREAD WM_USER + 102

HINSTANCE g_hinst = NULL;
HWND g_hwndDLG = NULL;
HWND g_TempDLG = NULL;
HBRUSH g_hbrBackground;
DWORD g_hThreadListId = 0;
int g_ListIndex = 0;


struct HookProcInfo{

TCHAR Operation[20];
TCHAR ProcessInfo[MAX_PATH];
};

#define WM_STOPTHREAD WM_USER + 101

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

switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hinst = (HINSTANCE)hModule;
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;

}
void WriteLog(HWND hWnd){

}
INT_PTR WINAPI ReList_DlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
){


HWND ReListView;
switch(uMsg)
{
case WM_INITDIALOG:
{
g_hbrBackground = CreateSolidBrush(RGB(66, 66, 66));
ReListView = GetDlgItem(hwndDlg ,IDC_RECLIST);
LVCOLUMN rlcol;
rlcol.mask = LVCF_TEXT | LVCF_WIDTH |LVCF_FMT;
rlcol.cx = 150;
rlcol.pszText = TEXT("时间");
rlcol.fmt = LVCFMT_CENTER;
ListView_InsertColumn(ReListView,1,&rlcol);
rlcol.cx = 300;
rlcol.pszText = TEXT("进程名称");
ListView_InsertColumn(ReListView,2,&rlcol);
rlcol.mask = LVCF_TEXT | LVCF_WIDTH;
rlcol.cx = 70;
rlcol.pszText = TEXT(" 运行状态");
ListView_InsertColumn(ReListView,3,&rlcol);

}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_RCLBTN:
MessageBox(hwndDlg,TEXT("清空列表成功!"),NULL,MB_ICONINFORMATION|MB_OK);
}
break;

case WM_CTLCOLORDLG:
return (LONG)g_hbrBackground;
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(255, 255, 255));
SetBkMode(hdcStatic, TRANSPARENT);
return (LONG)g_hbrBackground;
}

case WM_CLOSE:
//DeleteObject(g_hbrBackground);
break;
default:break;
}
return FALSE;
};

///////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////


HWND ProcRunDlg(){

g_hwndDLG = CreateDialog(g_hinst,MAKEINTRESOURCE(IDD_RECORDLISTBOX),NULL,ReList_DlgProc);

return g_hwndDLG;
}


我这个在win32与MFC中都能正常响应消息
dungeonsnd 2009-08-19
  • 打赏
  • 举报
回复
另外,我不打算在这个DLL中使用MFC的东西。
dungeonsnd 2009-08-19
  • 打赏
  • 举报
回复
如果有谁做过这样的DLL,请给个框架例子
(比如调用者调用DLL后,创建十个DLL实例,来创建十个子窗口,每个窗口过程可以正常的收到主窗口(调用者
发过来的消息,然后发送到正确的子窗口中,DLL中的子窗口过程进行处理),谢谢。 毕竟自己写框架不太成熟.(即使仿照 wtl and atl)

thank you

dungeonsnd@126.com
dungeonsnd 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 tr0j4n 的回复:]
给你提供学习WTL的几个网址

http://blog.csdn.net/orbit/archive/2006/04/14/663865.aspx
http://www.codeproject.com/KB/wtl/wtl4mfc1.aspx
[/Quote]

Thank u!
MoXiaoRab 2009-08-19
  • 打赏
  • 举报
回复
给你提供学习WTL的几个网址

http://blog.csdn.net/orbit/archive/2006/04/14/663865.aspx
http://www.codeproject.com/KB/wtl/wtl4mfc1.aspx
加载更多回复(8)

15,467

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧