我的应用程序是showontop类型窗口,弹出菜单(mastermenu)弹出光标位置,意味着在主窗体(demoForm)之外,由外部winapi消息(剪贴板更改)触发。
令人烦恼的问题是菜单在应用程序外部点击时不会消失,而不是点击任何菜单项或主表单,就像通常用来关闭菜单一样。重点是,我的应用程序保持在最顶层,菜单仍然浮动。
试图跟随很多文章,甚至从D7变为XE5都没有成功。检查过这个问题:Automatically Hide or Close PopUp Menu when Mouse Pointer is outside it - Delphi我的延迟定时器或托盘控制并不复杂。
具体来说,借用解决方案,我做到了这一点:
procedure TDemoForm.tmrMenumouseOutMonitorTimer(Sender: TObject);
var
hPopupWnd: HWND;
R: TRect;
PT: TPoint;
begin
hPopupWnd := FindWindow('#32768', mastermenu);
if hPopupWnd = 0 then Exit;
GetWindowRect(hPopupWnd, R);
GetCursorPos(Pt);
if PtInRect(R, Pt) then begin
//do something
end else begin
//do something
end;
end;
我试图用计时器(MenumouseOutMonitorTimer)轮询光标位置,以检测光标是否移出菜单(mastermenu)。如果它移出,我将发出.closeMenu()
但是,此代码抛出 - 在FindWindow()最后一个参数的D7 / XE5中的字符串,pAnsiChar / pwidestring不匹配。也许我应该使用FindWindowEx? XE5直接从TPopupMenu返回一些句柄,但我不知道如何使用它们来解决我的问题。
(在Win7上,也是针对XP)
我是初学者,任何帮助都将受到赞赏。
完整代码:
unit FmDemo;
interface
uses
System.Classes,
Vcl.Controls,
Vcl.StdCtrls,
Vcl.Forms, Menus, Dialogs, FileCtrl, ExtCtrls,PJCBView;// ....;
type
TDemoForm = class(TForm)
//......
PJCBViewer1: TPJCBViewer; //custom control
masterMenu: TPopupMenu;
tmrMenumouseOutMonitor: TTimer;
procedure tmrMenumouseOutMonitorTimer(Sender: TObject);
private
//........
procedure menuItemClickHandler(Sender: TObject);
end;
var
DemoForm: TDemoForm;
implementation
uses
Jpeg, Shellapi, Graphics, SysUtils, RichEdit, Messages;//GifImage
{$R *.dfm}
procedure tdemoform.menuItemClickHandler(Sender: TObject);
begin
//.......
end;
procedure TDemoForm.PJCBViewer1ClipboardChanged(Sender: TObject);
var
pnt: TPoint;
begin
demoform.BringToFront; //formStyle -> fsStayOnTop already
///////////////////////////////////
///menu under cursor display code//
///////////////////////////////////
if GetCursorPos(pnt) then
begin
masterMenu.Popup(pnt.X, pnt.Y);
end;
//remember to return focus to source window after each menu action (not implemented)
end;
procedure TDemoForm.tmrMenumouseOutMonitorTimer(Sender: TObject);
var
hPopupWnd: HWND;
R: TRect;
PT: TPoint;
begin
hPopupWnd := FindWindow('#32768', masterMenu);
if hPopupWnd = 0 then Exit;
GetWindowRect(hPopupWnd, R);
GetCursorPos(Pt);
if PtInRect(R, Pt) then begin
//do something
end else begin
//do something
end;
end;
//... other business logic
initialization
CF_RTF := RegisterClipboardFormat( richedit.CF_RTF );
end.
答案 0 :(得分:2)
这是一个不需要第三方控制的MCVE。
resp, err = client.Get("someurl")
var urls []string
if err != nil {
log.Fatal(err)
}
doc, err := html.Parse(strings.NewReader(resp.Body))
if err != nil {
log.Fatal(err)
}
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "a" {
for _, a := range n.Attr {
if a.Key == "href" {
fmt.Println(a.Val)
if strings.Contains(a.Val, "somestring") {
urls = append(urls, a.Val)
}
break
}
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
f(doc)
点击表单外部,弹出窗口不会被释放。
正如你所看到的,我必须人为地强加重现问题的条件,即弹出菜单时你的窗口不在前台。
正如你所链接的页面上的几个地方所提到的,为了正常发布弹出窗口,当你弹出菜单时你的窗口必须在前台,然后你不需要轮询并找到它然后手动释放它。 ...
implementation
uses
menus;
{$R *.dfm}
var
Pop: TPopupMenu;
Wnd: HWND;
procedure TForm1.FormCreate(Sender: TObject);
begin
Left := 200;
Top := 100;
Pop := TPopupMenu.Create(nil);
Pop.Items.Add(TMenuItem.Create(Pop));
Pop.Items[0].Caption := 'test';
Wnd := GetForegroundWindow;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SetForegroundWindow(Wnd); // comment this for the popup to be released when clicked outside
Pop.Popup(100, 50);
end;
不保证您的窗口会出现在前面。有关此问题和多个解决方案的详细信息,请参阅this question。