SDIAppForm是否能广播消息到它的MDIChild子窗口? (200分)

  • 主题发起人 主题发起人 blackbeam
  • 开始时间 开始时间
B

blackbeam

Unregistered / Unconfirmed
GUEST, unregistred user!
我写的代码里,MDIForm无法接收由SDIAppForm通过SendMessage(HWND_BROADCAST...)广播的消息。<br>但是非MDIForm子窗口就可以,是不是MDIForm有什么特殊的情况?请大家指教。<br>(我是重载WndProc方法来处理消息的。)<br>
 
广播应该是广播到系统中所以程序中吧,<br>假如你的程序接收到一个消息广播,那么是由application的winproc去接收的<br>然后做相应动作,比如,如果这个消息是系统要关机,那么它会通知FORM一个个关掉<br>(相当于运行mainform.close)<br>而且application它也不会将所以的消息传给所有FORM的<br><br>如果你想在自己的运行的两个以上的程序间传播消息,除了用广播外,当application的主FORM<br>接收到消息外,还要再把这消息再发给每个子FORM。<br>这样就相当于你的MDIFORM也收到了广播。
 
我的代码如下,请大家看看,我认为是MdiChild在消息处理上和其他类型的窗口有区别,但<br>不知道区别在哪里,着急啊!!!<br><br>mdichild子窗口dll<br>/////////////////////////////////////////////////////////////////////<br>library mdi;<br><br>{ Important note about DLL memory management: ShareMem must be the<br>&nbsp; first unit in your library's USES clause AND your project's (select<br>&nbsp; Project-View Source) USES clause if your DLL exports any procedures or<br>&nbsp; functions that pass strings as parameters or function results. This<br>&nbsp; applies to all strings passed to and from your DLL--even those that<br>&nbsp; are nested in records and classes. ShareMem is the interface unit to<br>&nbsp; the BORLNDMM.DLL shared memory manager, which must be deployed along<br>&nbsp; with your DLL. To avoid using BORLNDMM.DLL, pass string information<br>&nbsp; using PChar or ShortString parameters. }<br><br>uses<br>&nbsp; SysUtils,<br>&nbsp; Classes,<br>&nbsp; Windows,<br>&nbsp; Forms,<br>&nbsp; Unit1 in 'Unit1.pas' {Form1};<br><br>procedure Load(ParentApplication : TApplication; ParentForm : TForm); export; stdcall;<br>var<br>&nbsp; DllProc : Pointer;<br>begin<br>&nbsp; Application:=ParentApplication;<br>&nbsp; Form1:=TForm1.Create(ParentForm);<br>&nbsp; Form1.MyParentForm:=ParentForm;<br>&nbsp; Form1.MyParentApplication:=ParentApplication;<br>&nbsp; Form1.Show;<br>end;<br><br>procedure DLLUnloadProc(Reason : Integer); register;<br>begin<br>&nbsp; if Reason = DLL_PROCESS_DETACH then Application:=DllApplication;<br>end;<br><br>{$R *.RES}<br><br>exports<br>&nbsp; Load;<br><br>begin<br>&nbsp; DllApplication:=Application;<br>&nbsp; DllProc:=@DLLUnloadProc;<br>end.<br>/////////////////////////////////////////////////////////////////////<br><br>/////////////////////////////////////////////////////////////////////<br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>&nbsp; StdCtrls;<br><br>const<br>&nbsp; M_A_S = 'A';<br>&nbsp; M_B_S = 'B';<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; Button2: TButton;<br>&nbsp; &nbsp; Button3: TButton;<br>&nbsp; &nbsp; procedure FormCreate(Sender: TObject);<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; &nbsp; procedure Button2Click(Sender: TObject);<br>&nbsp; &nbsp; procedure Button3Click(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; M_A : WPARAM;<br>&nbsp; &nbsp; M_B : WPARAM;<br>&nbsp; &nbsp; procedure Do_M_A(var msg:TMessage); message 12345;<br>&nbsp; protected<br>&nbsp; &nbsp; procedure WndProc(var Message : TMessage); override;<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; &nbsp; MyParentForm : TForm;<br>&nbsp; &nbsp; MyParentApplication : TApplication; &nbsp; &nbsp;<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br>&nbsp; DllApplication : TApplication;<br><br>implementation<br><br>{$R *.DFM}<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br>&nbsp; M_A:=RegisterWindowMessage(M_A_S);<br>&nbsp; M_B:=RegisterWindowMessage(M_B_S);<br>end;<br><br>procedure TForm1.WndProc(var Message : TMessage);<br>begin<br>&nbsp; if Message.Msg = M_A then<br>&nbsp; &nbsp;ShowMessage('received : M_A from Mdi');<br>&nbsp; if Message.Msg = M_B then<br>&nbsp; &nbsp;ShowMessage('received : M_B from Mdi');<br><br>&nbsp; inherited WndProc(Message);<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br>&nbsp; //SendMessage(HWND_BROADCAST,M_A,0,0);<br>&nbsp; PostMessage(HWND_BROADCAST,M_A,0,0);<br>&nbsp; ShowMessage('sended : M_A');<br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br>&nbsp; SendMessage(HWND_BROADCAST,M_B,0,0);<br>&nbsp; ShowMessage('sended : M_B');<br>end;<br><br>procedure TForm1.Do_M_A(var msg:TMessage);<br>begin<br>&nbsp; ShowMessage('received : 12345 from Mdi');<br>end;<br><br>procedure TForm1.Button3Click(Sender: TObject);<br>begin<br>&nbsp; SendMessage(HWND_BROADCAST,12345,0,0);<br>end;<br><br>end.<br>/////////////////////////////////////////////////////////////////////<br><br>SDI框架<br>/////////////////////////////////////////////////////////////////////<br>unit Sdimain;<br><br>interface<br><br>uses Windows, Classes, Graphics, Forms, Controls, Menus,<br>&nbsp; Dialogs, StdCtrls, Buttons, ExtCtrls, ComCtrls, ImgList, StdActns,<br>&nbsp; ActnList, ToolWin, Messages;<br><br>const<br>&nbsp; M_A_S = 'A';<br>&nbsp; M_B_S = 'B';<br><br>type<br>&nbsp; TSDIAppForm = class(TForm)<br>&nbsp; &nbsp; OpenDialog: TOpenDialog;<br>&nbsp; &nbsp; SaveDialog: TSaveDialog;<br>&nbsp; &nbsp; ToolBar1: TToolBar;<br>&nbsp; &nbsp; ToolButton9: TToolButton;<br>&nbsp; &nbsp; ToolButton1: TToolButton;<br>&nbsp; &nbsp; ToolButton2: TToolButton;<br>&nbsp; &nbsp; ToolButton3: TToolButton;<br>&nbsp; &nbsp; ToolButton4: TToolButton;<br>&nbsp; &nbsp; ToolButton5: TToolButton;<br>&nbsp; &nbsp; ToolButton6: TToolButton;<br>&nbsp; &nbsp; ActionList1: TActionList;<br>&nbsp; &nbsp; FileNew1: TAction;<br>&nbsp; &nbsp; FileOpen1: TAction;<br>&nbsp; &nbsp; FileSave1: TAction;<br>&nbsp; &nbsp; FileSaveAs1: TAction;<br>&nbsp; &nbsp; FileExit1: TAction;<br>&nbsp; &nbsp; EditCut1: TEditCut;<br>&nbsp; &nbsp; EditCopy1: TEditCopy;<br>&nbsp; &nbsp; EditPaste1: TEditPaste;<br>&nbsp; &nbsp; HelpAbout1: TAction;<br>&nbsp; &nbsp; StatusBar: TStatusBar;<br>&nbsp; &nbsp; ImageList1: TImageList;<br>&nbsp; &nbsp; MainMenu1: TMainMenu;<br>&nbsp; &nbsp; File1: TMenuItem;<br>&nbsp; &nbsp; FileNewItem: TMenuItem;<br>&nbsp; &nbsp; FileOpenItem: TMenuItem;<br>&nbsp; &nbsp; FileSaveItem: TMenuItem;<br>&nbsp; &nbsp; FileSaveAsItem: TMenuItem;<br>&nbsp; &nbsp; N1: TMenuItem;<br>&nbsp; &nbsp; FileExitItem: TMenuItem;<br>&nbsp; &nbsp; Edit1: TMenuItem;<br>&nbsp; &nbsp; CutItem: TMenuItem;<br>&nbsp; &nbsp; CopyItem: TMenuItem;<br>&nbsp; &nbsp; PasteItem: TMenuItem;<br>&nbsp; &nbsp; Help1: TMenuItem;<br>&nbsp; &nbsp; HelpAboutItem: TMenuItem;<br>&nbsp; &nbsp; Message1: TMenuItem;<br>&nbsp; &nbsp; A1: TMenuItem;<br>&nbsp; &nbsp; B1: TMenuItem;<br>&nbsp; &nbsp; Dll1: TMenuItem;<br>&nbsp; &nbsp; LoadMdi1: TMenuItem;<br>&nbsp; &nbsp; procedure FileNew1Execute(Sender: TObject);<br>&nbsp; &nbsp; procedure FileOpen1Execute(Sender: TObject);<br>&nbsp; &nbsp; procedure FileSave1Execute(Sender: TObject);<br>&nbsp; &nbsp; procedure FileExit1Execute(Sender: TObject);<br>&nbsp; &nbsp; procedure HelpAbout1Execute(Sender: TObject);<br>&nbsp; &nbsp; procedure FormCreate(Sender: TObject);<br>&nbsp; &nbsp; procedure A1Click(Sender: TObject);<br>&nbsp; &nbsp; procedure B1Click(Sender: TObject);<br>&nbsp; &nbsp; procedure LoadMdi1Click(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; M_A : WPARAM;<br>&nbsp; &nbsp; M_B : WPARAM;<br>&nbsp; protected<br>&nbsp; &nbsp; procedure WndProc(var Message : TMessage); override; &nbsp; &nbsp;<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>&nbsp; T_ProvaChild = procedure (ParentApplication : TApplication; ParentForm : TForm); stdcall;<br><br>var<br>&nbsp; SDIAppForm: TSDIAppForm;<br><br>implementation<br><br>uses About;<br><br>{$R *.DFM}<br><br>procedure TSDIAppForm.FileNew1Execute(Sender: TObject);<br>begin<br>&nbsp; { Do nothing }<br>end;<br><br>procedure TSDIAppForm.FileOpen1Execute(Sender: TObject);<br>begin<br>&nbsp; OpenDialog.Execute;<br>end;<br><br>procedure TSDIAppForm.FileSave1Execute(Sender: TObject);<br>begin<br>&nbsp; SaveDialog.Execute;<br>end;<br><br>procedure TSDIAppForm.FileExit1Execute(Sender: TObject);<br>begin<br>&nbsp; Close;<br>end;<br><br>procedure TSDIAppForm.HelpAbout1Execute(Sender: TObject);<br>begin<br>&nbsp; AboutBox.ShowModal;<br>end;<br><br>procedure TSDIAppForm.FormCreate(Sender: TObject);<br>begin<br>&nbsp; M_A:=RegisterWindowMessage(M_A_S);<br>&nbsp; M_B:=RegisterWindowMessage(M_B_S);<br>end;<br><br>procedure TSDIAppForm.A1Click(Sender: TObject);<br>begin<br>&nbsp; SendMessage(HWND_BROADCAST,M_A,0,0);<br>&nbsp; ShowMessage('sended : M_A');<br>end;<br><br>procedure TSDIAppForm.B1Click(Sender: TObject);<br>begin<br>&nbsp; SendMessage(HWND_BROADCAST,M_B,0,0);<br>&nbsp; ShowMessage('sended : M_B'); &nbsp;<br>end;<br><br>procedure TSDIAppForm.WndProc(var Message : TMessage);<br>begin<br>&nbsp; if Message.Msg = M_A then<br>&nbsp; &nbsp;ShowMessage('received : M_A');<br>&nbsp; if Message.Msg = M_B then<br>&nbsp; &nbsp;ShowMessage('received : M_B');<br><br>&nbsp; inherited WndProc(Message);<br>end;<br><br>procedure TSDIAppForm.LoadMdi1Click(Sender: TObject);<br>var<br>&nbsp; DllHandle : THandle;<br>&nbsp; ProcAddr : FarProc;<br>&nbsp; ProvaChild : T_ProvaChild;<br>begin<br>&nbsp; DllHandle:=LoadLibrary('mdi.dll');<br>&nbsp; ProcAddr:=GetProcAddress(DllHandle,'Load');<br>&nbsp; if ProcAddr &lt;&gt; nil then<br>&nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp;ProvaChild:=ProcAddr;<br>&nbsp; &nbsp; &nbsp;ProvaChild(Application,SDIAppForm);<br>&nbsp; &nbsp;end<br>&nbsp; else<br>&nbsp; ShowMessage('调用模块失败!');<br>end;<br><br>end.<br>/////////////////////////////////////////////////////////////////////<br><br>
 
就差两秒!<br>如yhaochuan老兄所说,就是不必用:<br>SendMessage(HWND_BROADCAST,M_A,0,0);<br>而使用:<br>SendMessage(hWnd,M_A,0,0);<br>那我的SDI框架必须得到当前打开的MdiChild子窗口列表,然后对其一一发送消息,是这样<br>吗?但是我不会做,还请赐教。<br>&nbsp;
 
有个疑问,DLL用‘A’在系统注册消息得到MSG_A<br>EXE也用‘A’在系统注册消息得到MSG_B,那么MSG_A是否等于MSG_B呢。<br>照帮助看,RegisterWindowMessage会得到唯一的消息。
 
http://www.vclxx.org/DELPHIGB/DEFAULT.HTM里面有一个范例:<br>MDIMSG.ZIP <br>示范 MDI 父子窗口以使用者自订窗口消息(User Define Windows Message) 沟通的范例程序,作者:钱达智。 <br>(http://www.vclxx.org/DELPHI/D32SAMPL/MDIMSG.ZIP)<br>里面有如果取得子窗口列表并发送消息的。<br>你看看吧,我也温故知新。
 
取得子窗口列表代码:<br>procedure dosomething;<br>var<br>&nbsp; I: Integer;<br>begin<br>&nbsp; with Form1 do<br>&nbsp; &nbsp; for I := MDIChildCount-1 downto 0 do<br>&nbsp; &nbsp; &nbsp; MDIChildren.Close;//有了MDIChildren.Handle,就可以SEND消息了。<br>end;
 
我刚刚查过,可以通过下列代码访问:<br>for i:=1 to SDIAppForm.MDIChildCount do<br>&nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; SendMessage(SDIAppForm.MDIChildren.Handle,M_A,0,0);<br>&nbsp; &nbsp; &nbsp; ShowMessage('sended : M_A');<br>&nbsp; &nbsp;end;<br>但是倒霉的是我的MDIChild窗口是从一个dll文件中创建的,而SDIAppForm无法对这样的<br>窗口进行计数。(我在SDIAppForm中调用是成功的)。
 
能不能将SDIAPPFORM做为一个参数传入DLL,MDIFORM在CREATE的时候以<br>传入的参数做为父FORM(一个思路)
 
算了,可能还要想一下,先把分给老兄得了。
 
或者调用DLL产生MDIFORM的时候,顺便返回MDIFORM的handle,<br>mainFORM把这个HANDLE保存到数组中,有消息的时候,循环这个数组,逐个传消息。
 
别忘了问题真正解决的时候把解决方法POST上来。
 
是否能有更好的方法?<br><br>//调用DLL模块<br>procedure TSDIAppForm.LoadMdi1Click(Sender: TObject);<br>var<br>&nbsp; DllHandle : THandle;<br>&nbsp; ProcAddr : FarProc;<br>&nbsp; ProvaChild : T_ProvaChild;<br>begin<br>&nbsp; DllHandle:=LoadLibrary('mdi.dll');<br>&nbsp; ProcAddr:=GetProcAddress(DllHandle,'Load');<br>&nbsp; if ProcAddr &lt;&gt; nil then<br>&nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp;ProvaChild:=ProcAddr;<br>&nbsp; &nbsp; &nbsp;hMdiChild:=ProvaChild(Application,SDIAppForm);<br>&nbsp; &nbsp;end<br>&nbsp; else<br>&nbsp; &nbsp;ShowMessage('调用模块失败!');<br>end;<br><br>//Dll模块<br>function Load(ParentApplication : TApplication; ParentForm : TForm) : HWND; export; stdcall;<br>var<br>&nbsp; DllProc : Pointer;<br>begin<br>&nbsp; Application:=ParentApplication;<br>&nbsp; Form1:=TForm1.Create(ParentForm);<br>&nbsp; Form1.MyParentForm:=ParentForm;<br>&nbsp; Form1.MyParentApplication:=ParentApplication;<br>&nbsp; Form1.ParentWindow:=ParentForm.Handle;<br>&nbsp; Form1.Show;<br>&nbsp; result:=Form1.Handle;<br>end;<br>
 
后退
顶部