c# - Block closing WPF window (from a different thread) if OpenFileDialog is open -
to clear things before mention obvious choice, calling showdialog , not show method!!!
i block close (invoked different thread) off wpf window if openfiledialog open.
here code have (reduced show problem):
public class foowindow : window { public foowindow() { initializecomponent(); this.closing += onclosing; } public void opendialogandcloseme() { var ofd = new openfiledialog(); thread th = new thread(() => closeme()); th.start(); ofd.showdialog(this); } public void closeme() { system.threading.thread.sleep(2000); //give openfiledialog time pop up... //since method gets called different thread invoke it... this.dispatcher.invoke(() => this.close()); } private void onclosing(object sender, canceleventargs e) { //check if openfiledialog still open , block close... e.cancel = true; } }
the problem facing onclosing part, how openfiledialog (or other dialog in case).
i have searched web , found win32 methods like:
[dllimport("user32")] [return: marshalas(unmanagedtype.bool)] private static extern bool enumchildwindows(intptr window, enumedwindow callback, arraylist lparam); [dllimport("user32.dll", entrypoint = "findwindowex", charset = charset.auto)] static extern intptr findwindowex(intptr hwndparent, intptr hwndchildafter, string lpszclass, string lpszwindow);
i have tried them both return 0 children, ideas what's going wrong?
here full code tried far:
//replace above onclosing implementation... 3 return false private void onclosing(object sender, canceleventargs e) { //check if openfiledialog still open , block close... var hwnd = new windowinterophelper(this).handle; if (windowhandling.getchildren(hwnd).any()) e.cancel = true; if (windowhandling.getchildrenv2(hwnd).any()) e.cancel = true; if (windowhandling.getchildrenv3(hwnd).any()) e.cancel = true; } public static class windowhandling { private delegate bool enumedwindow(intptr handlewindow, arraylist handles); [dllimport("user32")] [return: marshalas(unmanagedtype.bool)] private static extern bool enumchildwindows(intptr window, enumedwindow callback, arraylist lparam); [dllimport("user32.dll", entrypoint = "findwindowex", charset = charset.auto)] static extern intptr findwindowex(intptr hwndparent, intptr hwndchildafter, string lpszclass, string lpszwindow); private static bool getwindowhandle(intptr windowhandle, arraylist windowhandles) { windowhandles.add(windowhandle); return true; } public static ienumerable<intptr> getchildren(intptr hwnd) { if (hwnd == intptr.zero) return enumerable.empty<intptr>(); var x = new windowhandleinfo(hwnd); return x.getallchildhandles(); } public static ienumerable<intptr> getchildrenv2(intptr hwnd) { var windowhandles = new arraylist(); enumedwindow callbackptr = getwindowhandle; enumchildwindows(hwnd, callbackptr, windowhandles); return windowhandles.oftype<intptr>(); } public static ienumerable<intptr> getchildrenv3(intptr hparent) { var result = new list<intptr>(); var ct = 0; var maxcount = 100; var prevchild = intptr.zero; while (true && ct < maxcount) { var currchild = findwindowex(hparent, prevchild, null, null); if (currchild == intptr.zero) break; result.add(currchild); prevchild = currchild; ++ct; } return result; } //http://stackoverflow.com/questions/1363167/how-can-i-get-the-child-windows-of-a-window-given-its-hwnd private class windowhandleinfo { private delegate bool enumwindowproc(intptr hwnd, intptr lparam); [dllimport("user32.dll", setlasterror = true)] [return: marshalas(unmanagedtype.bool)] private static extern bool enumchildwindows(intptr window, enumwindowproc callback, intptr lparam); private readonly intptr _mainhandle; public windowhandleinfo(intptr handle) { _mainhandle = handle; } public ienumerable<intptr> getallchildhandles() { var childhandles = new list<intptr>(); var gcchildhandleslist = gchandle.alloc(childhandles); var pointerchildhandleslist = gchandle.tointptr(gcchildhandleslist); try { var childproc = new enumwindowproc(enumwindow); var x = enumchildwindows(this._mainhandle, childproc, pointerchildhandleslist); if (x == false) { var error = marshal.getlastwin32error(); } } { gcchildhandleslist.free(); } return childhandles; } private static bool enumwindow(intptr hwnd, intptr lparam) { var gcchildhandleslist = gchandle.fromintptr(lparam); if (gcchildhandleslist.target == null) return false; var childhandles = gcchildhandleslist.target list<intptr>; if (childhandles != null) childhandles.add(hwnd); return true; } } }
you can solve boolean value tracking if it's open or not:
bool dialogopen = false; public void opendialogandcloseme() { var ofd = new openfiledialog(); thread th = new thread(() => closeme()); th.start(); dialogopen = true; ofd.showdialog(this); dialogopen = false; } private void onclosing(object sender, canceleventargs e) { //check if openfiledialog still open , block close... if(dialogopen) { e.cancel = true; } }
Comments
Post a Comment