自定义类如下,因为代码比较多,为了看清楚,我把不相关的部分删除了。<br>===========================<br>unit TRouteEditorClass;<br><br>interface<br>uses Controls, Classes, MapXLib_TLB, Variants, TeEngine, windows, SysUtils,<br> frmuRouteSimpleInfo, Math,TypeOfPoint,TRoadRuleClass,frmuRouteDetailInfo,<br> dchyMapModule, Dialogs, DataModuleAdo,<br> frmuRouteDataWin, uConstDefine, PSMainUnit,Messages,<br> uRoutePlanning, uPointSortAndSearch, ProjectionAndSort;<br>type TRouteEditor = class(TMap)<br><br> private<br> { Private declarations }<br> m_IriMouseMoveEvent: TMouseMoveEvent;<br> m_IriKeyDownEvent : TKeyEvent; //keydown 和keyPress用一个就可以了,能达到目的就行,<br> m_IriMapKeyPress : TKeyPressEvent; // 我这里写了两个是想都试一下,哪个能用用哪个,<br> //按说要有一个弄同的话,另一个应该也没问题<br> <br> m_frmRouteDetailInfo : TfrmRouteDetailInfo; //信息显示窗口<br><br><br> procedure MyKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);<br><br> procedure MyKeyPress(Sender: TObject; var Key: Char);<br><br> public<br> { public declarations }<br><br> constructor Create(currentMap : TMap;roadLayer,nodeLayer,GuiHuaRouteLayer,customerLayer : CMapXLayer);<br> function CreateAddRouteTool: Integer;<br> function InstallAddRouteTool(): Boolean;<br> function UnInstallAddRouteTool(): Boolean;<br> function GetToolNum(): Integer;<br> end;<br><br>const<br> MAP_ADDROUTE_TOOL = 805;<br> ADD_ROUTE_TOLERANCE = 30; //手工画线路时,必须和道路中线的最大距离,超出此距离则认为画线无效<br><br>implementation<br><br>var<br> myMapModule : TdchyMapModule;<br><br>{ TRouteEditor }<br><br>function TRouteEditor.InstallAddRouteTool: Boolean;<br>begin<br> if m_pMap <> nil then<br> begin<br> //保存原先的事件处理函数状态<br> m_IriKeyDownEvent := m_pMap.OnKeyDown;<br> m_IriMapKeyPress := m_pMap.OnKeyPress;<br><br> m_pMap.OnKeyDown := MyKeyDown;<br> m_pMap.OnKeyPress := MyKeyPress;<br> result := True;<br> end<br> else<br> result := False;<br>end;<br><br>procedure TRouteEditor.MyKeyDown(Sender: TObject; var Key: Word;<br> Shift: TShiftState);<br>begin<br> if (m_pMap.CurrentTool = MAP_ADDROUTE_TOOL) and (Key = VK_ESCAPE) then begin<br> // 我会在这里写业务相关代码,以相应键盘发送VK_ESCAPE事件***********<br> end;<br><br> //退出自定义工具<br> m_pMap.CurrentTool := miArrowTool;<br> myMapModule.DeleteTempAnimationLayer(m_pMap, m_strRuleFlagLayer);<br> UnInstallAddRouteTool;<br> end;<br><br> if @m_IriKeyDownEvent <> nil then<br> m_IriKeyDownEvent(Sender,Key, Shift);<br>end;<br><br><br>procedure TRouteEditor.MapMouseMove(Sender: TObject; Shift: TShiftState; X,<br> Y: Integer);<br>begin<br> //显示信息窗口出来*******************<br> if m_frmRouteDetailInfo = nil then <br> m_frmRouteDetailInfo := Tm_frmRouteDetailInfo.Create(nil);<br> m_frmRouteDetailInfo.Show;<br><br> if @m_IriMouseMoveEvent <> nil then<br> m_IriMouseMoveEvent(Sender, Shift, X, Y);<br>end;<br><br>function TRouteEditor.UnInstallAddRouteTool: Boolean;<br>begin<br> if m_pMap <> nil then<br> begin<br> //回复原先的事件处理函数状态<br><br> m_pMap.OnKeyDown := m_IriKeyDownEvent;<br> m_pMap.OnKeyPress := m_IriMapKeyPress;<br><br> m_IriKeyDownEvent := nil;<br> m_IriMapKeyPress := nil;<br> result := True;<br> end<br> else<br> result := False;<br>end;<br><br>procedure TRouteEditor.MyKeyPress(Sender: TObject; var Key: Char);<br>begin<br> if (m_pMap.CurrentTool = MAP_ADDROUTE_TOOL) and ((Key = 'u') or (Key = 'U')) then begin<br> // 我会在这里写业务相关代码,以相应键盘事件***********<br> end;<br> <br> //退出自定义工具<br> UnInstallAddRouteTool;<br> end;<br><br><br> if @m_IriMapKeyPress <> nil then<br> m_IriMapKeyPress(Sender, Key);<br>end;<br><br>end.<br>========================<br><br><br>调用代码<br>===========<br> //初始化RouteEditor类,画线工具<br> if RouteEditor = nil then<br> begin<br> RouteEditor := TRouteEditor.Create();<br> RouteEditor.CreateAddRouteTool;<br> end;<br><br>======================<br><br>由于自定义类截获了mouseMove事件,所有在发生mouseMove时会把信息显示窗口(TfrmRouteDetailInfo)show出来,这样主窗体就接受不到键盘事件了。<br><br>我按照 饭前饭后 的方法,在信息显示窗口(TfrmRouteDetailInfo)类中 增加keyPress事件处理函数用sendmessage传给主窗口,但跟踪结果显示 信息显示窗口根本就没有发生keyPress事件,就是说下面的代码没有执行<br>procedure TfrmRouteDetailInfo.FormKeyPress(Sender: TObject; var Key: Char);<br>var<br> MainFormTitle : array[0..127] of char;<br> Hold : string;<br> Found : HWND;<br>begin<br> inherited;<br> //只允许有一个实例运行,如果已经有一个在运行则激活它<br> Hold := frmAPMain.Caption; //取得程序的标题<br> StrPCopy(MainFormTitle, Hold); // 原窗口标题<br> Found := FindWindow(nil, MainFormTitle); // 查找窗口<br> if Found <> 0 then<br> begin<br> SendMessage(Found, WM_CHAR, Ord('u'), 0);<br> SendMessage(Found, WM_CHAR, Ord('U'), 0);<br> end;<br>end;