Reading c++ window in C# using handler -
i implementing plugin product called amibroker in c#.
amibroker trading software has exposed few functions can used 3rd party vendors pass stock data solution. so, can create plugin in c# can recognized amibroker.
in scenario getting handler of main window of amibroker [note : amibroker written in c++] in c# can retrieve handler of main window, using handle can read data of window e.g. child windows, panels showing stock lists or things visible user, , if so, how go doing this?
you can, it's messy. literally worked on similar. pinvoke.net great stuff, i'll show examples of how i'd find controls. if amibroker has documentation control names or accessiblenames or allows find exact controls you're looking for, that'd killer. because if they're ambiguously named, you're gonna have helluva time finding ones you're looking for. basically, you'll want enumchildwindows on handle have, iterate through them , unique property allow find control want. you'll need execute specific sendmessage text off of control (getwindowtext or whatever it's called works labels). code follows, adapted or swiped pinvoke.net @ point (great starting point):
[dllimport("user32")] [return: marshalas(unmanagedtype.bool)] private static extern bool enumchildwindows(intptr window, enumwindowproc callback, intptr i); public static extern uint getclassname(intptr handle, stringbuilder name, int maxlength); public delegate bool enumwindowproc(intptr hwnd, intptr parameter); private static list<intptr> getchildwindows(intptr parent) { list<intptr> result = new list<intptr>(); gchandle listhandle = gchandle.alloc(result); try { enumwindowproc childproc = new enumwindowproc(enumwindow); enumchildwindows(parent, childproc, gchandle.tointptr(listhandle)); } { if (listhandle.isallocated) listhandle.free(); } return result; } private static bool enumwindow(intptr handle, intptr pointer) { gchandle gch = gchandle.fromintptr(pointer); list<intptr> list = gch.target list<intptr>; if (list == null) { throw new invalidcastexception("gchandle target not cast list<intptr>"); } list.add(handle); // can modify check see if want cancel operation, return null here return true; } //this 1 you'll call! public static intptr getwindowbyclass(intptr mainwindow, string name) { list<intptr> windows = getchildwindows(mainwindow); foreach (intptr window in windows) { stringbuilder response = new stringbuilder(); response.capacity = 500; if (getclassname(window, response, response.capacity) > 0) if (response.tostring() == name) return window; } return intptr.zero; }
so iterates through whole set of child windows handle have on app, sees if class name matches control you're looking for, returns it. there thousands of ways improve (search ones want in single shot, findwindow may work class name, etc.) wanted show more how it's done, not declare how should done. finally, call text window/control follows (also adapted pinvoke.net: under user32.dll stuff):
public static string gettext(intptr control) { stringbuilder builder = new stringbuilder(40); intptr result = intptr.zero; uint response = sendmessagetimeouttext(control, 0xd, 40, builder, apitypes.sendmessagetimeoutflags.smto_normal, 2000, out result); return builder.tostring(); } [dllimport("user32.dll", entrypoint = "sendmessagetimeout", setlasterror = true, charset = charset.auto)] public static extern uint sendmessagetimeouttext( intptr hwnd, int msg, // use wm_gettext int countofchars, stringbuilder text, apitypes.sendmessagetimeoutflags flags, uint utimeoutj, out intptr result); [flags] public enum sendmessagetimeoutflags : uint { smto_normal = 0x0, smto_block = 0x1, smto_abortifhung = 0x2, smto_notimeoutifnothung = 0x8 }
edit: addendum: application worked on access form didn't have unique control names, ended using spy++ determine place in window hierarchy , pulling children , selecting each child in turn. god if have go route, because may not consistent @ all, if need on form isn't created, or it's hidden behind 1 jumped in z-order (breaking hierarchical list you're searching from). said, should know enumchildwindows enum child windows given window, no matter in hierarchy. if have drill down , search each control parent , parent's parent, you'll need use findwindowex, , declare last child looked @ (or intptr.zero if want first child):
[dllimport("user32.dll", setlasterror = true)] public static extern intptr findwindowex(intptr parenthandle, intptr childafter, string classname, string windowtitle);
Comments
Post a Comment