提出两个问题,请大家进来看看,谢谢!(300分)

  • 主题发起人 主题发起人 cqwty
  • 开始时间 开始时间
C

cqwty

Unregistered / Unconfirmed
GUEST, unregistred user!
第一个问题是,如何在多线程中实现消息循环,我记得以前有大富翁写过说用隐藏窗体来实现,但是由于没有全文检索,找起来麻烦,哪位知道,麻烦贴一下,当然,也可以把你的经验贴出来,谢谢!
第二个问题是,在一个dll中,我想将调用该dll的程序的主窗体的句柄作为参数传入dll中,然后保存下来,供dll中的其他函数使用,可是不行,麻烦大家发表一下解决方法,谢谢!
 
1. http://www.delphibbs.com/delphibbs/dispq.asp?lid=105410
2. 看看这个帖子: http://www.delphibbs.com/delphibbs/dispq.asp?lid=2288611
下面是摘录:
type
mypointer=procedure(form:Tform);Far;external;
var
Hinst:Thandle;
showform:mypointer;
begin
Hinst:=loadlibrary('yproject_dll');//Load一个Dll,按文件名找。
showform:=getprocaddress(Hinst,'showform');//按函数名找,大小写敏感。如果你知道自动化对象的本质就清楚了。
showform(application.mainform);//找到函数入口指针就调用。
Freelibrary(Hinst);
end;

七 在DLL建立一个TForM
1 把你的Form Uses到Dll中,你的Form用到的关联的单元也要Uses进来[这是最麻烦的一点,因为你的Form或许Uses了许多特殊的单元或函数]
2 传递一个Application参数,用它建立Form.
八 在DLL中建立一个TMDIChildForM
1 Dll中的MDIForm.FormStyle不用为fmMDIChild.
2 在CreateForm后写以下两句:
function ShowForm(mainForm:TForm):integer;stdcall
var
Form1: TForm1;
ptr:PLongInt;
begin
ptr:=@(Application.MainForm);//先把dll的MainForm句柄保存起来,也无须释放,只不过是替换一下
ptr^:=LongInt(mainForm);//用主调程序的mainForm替换DLL的MainForm。MainForm是特殊的WINDOW,它专门管理Application中的Forms资源.
//为什么不直接Application.MainForm := mainForm,因为Application.MainForm是只读属性
Form1:=TForm1.Create(mainForm);//用参数建立
end;
 
问题已经解决了。在此我贴点解决后的代码上来,后面的人可以不用再问这个问题了。
1.多线程中实现消息循环
unit unSignalThreadsMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TfrmSgnThreads = class(TForm)
mmMsgLog: TMemo;
btnNewThread: TButton;
btnSendSignal: TButton;
Button1: TButton;
procedure btnNewThreadClick(Sender: TObject);
procedure btnSendSignalClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
fHandle: THandle;
public
{ Public declarations }
end;

TTestThread = class(TThread)
private
FSignalShutdown: boolean;
FWinHandle: HWND;
procedure DeallocateHWnd(Wnd: HWND);
protected
procedure Execute;
override;
procedure WndProc(var msg: TMessage);
public
constructor Create;
destructor Destroy;
override;
procedure PrintMsg;
property WinHandle: HWND read FWinHandle;
end;

var
frmSgnThreads: TfrmSgnThreads;
implementation
var
WM_SHUTDOWN_THREADS: Cardinal;
{$R *.dfm}
{ TTestThread }
procedure TTestThread.DeallocateHWnd(Wnd: HWND);
var
Instance: Pointer;
begin
Instance := Pointer(GetWindowLong(Wnd, GWL_WNDPROC));
if Instance <> @DefWindowProc then
// make sure we restore the old, original windows procedure before leaving
SetWindowLong(Wnd, GWL_WNDPROC, Longint(@DefWindowProc));
FreeObjectInstance(Instance);
DestroyWindow(Wnd);
end;

constructor TTestThread.Create;
begin
FSignalShutdown := False;
FWinHandle := AllocateHWND(WndProc);
inherited Create(False);
end;

destructor TTestThread.Destroy;
begin
DeallocateHWnd(FWinHandle);
inherited;
end;

procedure TTestThread.Execute;
begin
FreeOnTerminate := True;
while NOT FSignalShutdowndo
begin
Sleep(10);
end;
Synchronize(PrintMsg);
end;

procedure TTestThread.PrintMsg;
begin
frmSgnThreads.mmMsgLog.Lines.Add('Thread ' + IntToStr(ThreadID) + ' shuttingdo
wn.');
end;

procedure TfrmSgnThreads.btnNewThreadClick(Sender: TObject);
var
tmpThread: TTestThread;
begin
tmpThread := TTestThread.Create;
mmMsgLog.Lines.Add('Thread ' + IntToStr(tmpThread.ThreadID) + ' running.');
mmMsgLog.Lines.Add(IntToStr(tmpThread.WinHandle));
fHandle := tmpThread.WinHandle;
end;

procedure TTestThread.WndProc(var msg: TMessage);
begin
if Msg.Msg = WM_COPYDATA then
begin
//FSignalShutdown := True;
ShowMessage(IntToStr(PCopyDataStruct(msg.LParam)^.dwData));
end
else
Msg.Result := DefWindowProc(FWinHandle, Msg.Msg, Msg.wParam, Msg.lParam);
end;

procedure TfrmSgnThreads.btnSendSignalClick(Sender: TObject);
begin
SendMessage(wnd_broadcast, WM_SHUTDOWN_THREADS, 0, 0);
end;

procedure TfrmSgnThreads.FormCreate(Sender: TObject);
begin
//WM_SHUTDOWN_THREADS := RegisterWindowMessage('TVS_Threads');
end;

procedure TfrmSgnThreads.Button1Click(Sender: TObject);
var
cds: TCopyDataStruct;
begin
cds.dwData := 100;
cds.cbData := 0;
cds.lpData := nil;
SendMessage(fHandle,WM_COPYDATA,0,LongInt(@cds));
end;

end.
2.如何传入参数到dll中,就是使用内存映象文件来解决了。具体细节,自己看看内存映象。
 
接受答案了.
 
后退
顶部