What is the proper way to subclass a tab control in winAPI, having windows perform both the default drawing and your own. Because BeginPaint() and EndPaint() are calling within the default proc, I don't see a way to do this. I did get it working with GetDC(), but it had a very bugs which annoyed the hell out of me.
If what I am asking is impossible, what is the best way to draw the tabs by myself?
Subclassing is not required in your situation. The tab control supports the TCS_OWNERDRAWFIXED style bit, which allows its parent window to handle WM_DRAWITEM messages and draw the tabs itself.
There's a nice exemple on Codeguru. It uses MFC but don't let that stop you. Check out their CTabCtrlEx::DrawItem() method.
Related
I was wondering how can I read text of a control that doesn't have an HWND. For instance, the print dialog in office 2007 doesn't have HWND on all of its controls (only a few).
Is there anyway to get the text from these controls?
I believe they're simply drawn on the window and react using HITTEST, but I'm not sure, so I'm asking you guys :-).
Thanks for your help!
Generally, there is no guaranteed way to do that. However, chances are you can get the text (and other info about the controls) using the IAccessible interface. Most Microsoft products implement this interface on most of the UI elements: this is how screen readers for disabled people work
For a generic windowless control, all you can assume is that the text exists only as pixels on the screen, so the only way to read it is with OCR.
If you can learn more information about the specific controls you want to inspect, then you might learn that the windowless control has a parent window that handles messages on its behalf, or that the control has a COM object you can manipulate, or that the control honors the Windows accessibility API. If you don't know anything else about the control, then all you have are the pixels.
I know this type of thing is looked negatively upon but I write software for people with disabilities and sometimes good gui practices don't make sense. In this case, the user interacts with a assistive interface and under certain conditions, my control app needs to prompt the user with a question. My background process creates a dialog (I'm using wxwidgets wxDialog class) and calls Show(). The dialog box appears but it does not have focus (the application that the user was previously using keeps it). Since my users can't use mice, they can't simply click on the window. I've tried calling show and then followed by SetFocus(HWND) but that doesn't do it. What's the problem? Is this even possible? Window7. I'm thinking that it might have something to do with it being a dialog and not a full window (wxFrame). Any help is greatly appreciated.
Try using SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE)
Unfortunately, not only is it 'looked negatively upon', but it is not possible. There's no getting around this; ask yourself what would happen if every application could do this? Obviously, if you can put your dialog on top of the other application, it can do exactly the same back to you.
http://blogs.msdn.com/b/oldnewthing/archive/2010/11/25/10096329.aspx
The only think I can think of would be for you to put a notification icon in the system tray, and then have it display a notification balloon.
I had to do something like this before. Simply calling functions like SetForegroundWindow or SetWindowPos didn't do the trick.
I ended up using this ForceForegroundWindow function (1st one) and it works pretty well.
I know this is Delphi code, but the API is the same and Delphi is a pretty simple language.
I want to make a C++ button on Start>Run i.e but when I do it will not do signalled event?
Im sorry I have seen that you do not get the question.
Ok basically when you create a button with CreateWindowEx(); I want to do that but put on a different window with SetPArent which I have already done now the button does not work so I need my program to someone get when it is clicked from the Run window as example!
And yes you have it, but it's not making the button is the problem it's getting when it's clicked with my program since it does not belong to it anymore!
You need to apply the ancient but still-supported technique known in Windows as subclassing; it is well explained here (15-years-old article, but still quite valid;-). As this article puts it,
Subclassing is a technique that allows
an application to intercept messages
destined for another window. An
application can augment, monitor, or
modify the default behavior of a
window by intercepting messages meant
for another window.
You'll want "instance subclassing", since you're interested only in a single window (either your new button, or, the one you've SetParented your new button to); if you decide to subclass a window belonging to another process, you'll also need to use the injection techniques explained in the article, such as, injecting your DLL into system processes and watching over events with a WH_CBT hook, and the like. But I think you could keep the button in your own process even though you're SetParenting it to a window belonging to a different process, in which case you can do your instance subclassing entirely within your own process, which is much simpler if feasible.
"Superclassing" is an alternative to "subclassing", also explained in the article, but doesn't seem to offer that many advantages when compared to instance subclassing (though it may compared with global subclassing... but, that's not what you need here anyway).
You'll find other interesting articles on such topics here, here, and here (developing a big, rich C++ library for subclassing -- but, also showing a simpler approach based on hooks which you might prefer). Each article has a pretty difference stance and code examples, so I think that having many to look at may help you find the right mindset and code for your specific needs!
OK, I'll do my very best - as I understand you, you're trying to inject a button into some existing window. That meaning: Your tool creates a button in some window that does not belong to your application. Now, you want to be notified when that button is pressed. Am I correct so far?
To be notified about the button being pressed, you need to get the respective window message, which will only work if you also "inject" a different WndProc into the window. Actually I have no idea how that should work, but I faintly remember functions like GetWindowLong and SetWindowLong. Maybe they will help?
EDIT
I've searched MSDN a little: While you can get the address of a window's WndProc using GetWindowLong, you can not set the WndProc using SetWindowLong on Windows NT/2000/XP (and up I suppose). See here (MSDN).
So what you could do is install a global message hook that intercepts all window messages, filter those for the window you've injected the button into and then find your message. If you have trouble with this, however, I'm the wrong person to ask, because it's been years ago since I've done anything like that, but it would be stuff for a new question.
EDIT 2
Please see Alex Martinellis answer for how to define the hook. I think he's describing the technique I was referring to when I talked about defining global message hooks to intercept the window messages for the window you injected your button into.
I need to know when my Window goes out of input focus, so I overloaded the OnKillFocus() method of the CWnd.
However it doesn't invoke this method when I focus another application (alt+tab), or even minimize the window. But it DOES invoke the method when I restore it from being minimized. Are these the intended times for it to trigger this method?
I think you'll need a CWnd::OnActivateApp() handler if you need to be sure of being notified when your application is switched out.
OnKillFocus() is normally only used consistently for controls that have a concept of gaining the focus - buttons, edit boxes, list boxes, etc. Normally CWnd does not accept the focus, so you can't rely on that - I'm surprised you get it at all.
In addition to WM_ACTIVATEAPP mentioned above, there's also WM_ACTIVATE when switching between windows within the same application you might want to trap.
I'm creating a plugin framework, where my application loads a series of plugin DLL's, then creates a new window and pass this new window's handle to the plugin. The plugin can, then, use this handle to create their own GUI.
Everything seems to be working very well. The only problem is that when I press TAB on a plugin widget (An editbox, for example), it doen't jump to another widget. I figured out that some Windows messages are passed, and some others aren't. The WM_KEYDOWN is passed for other keys, because I can type on the editbox, but this message doesn't handle TAB key.
Hope somebody has a hint.
I'm using Borland VCL with CBuilder, but I think I could use any framework under WIN32 to create these plugins, since they never know how their parent windows were created.
It's very complex matter indeed.
When you hit TAB focus jumps to another control only when these controls belong to a Modal Dialog Box. In fact there are some buttons like ESC, LEFT, RIGHT, DOWN, UP, TAB which modal dialog message function treats in a special way. If you want these keys to behave in similar way with modeless dialog box or any other window you should change you message processing function and use IsDialogMessage inside. You'll find more information about IsDialogMessage function in MSDN also to better understand this stuff you may check as well Dialog Boxes section.
And, as was mentioned before, you should set WS_TABSTOP and WS_GROUP styles when needed.
Good luck!
I believe you'll have to take the following steps:
Subclass your edit controls (and other controls as needed).
Capture the WM_KEYDOWN message in your edit control's WndProc.
Check to see if the shift key is currently held down (using GetKeyState or similar).
Call GetWindow, passing in a handle to your edit control and either GW_HWNDPREV or GW_HWNDNEXT depending on whether shift is held down. This will give you the handle to the window that should receive focus.
Call SetFocus and pass in the window handle you got in step 4.
Make sure you handle the case where your edit controls are multiline, as you might want to have a real tab character appear instead of moving to the next control.
Hope that helps!
I believe you suffer from having a different instance of the VCL in each of your dlls and exes. Classes from the dll are not the same as the ones from your exe, even if they are called the same. Also global variables (Application, Screen) are not shared between them. Neither is the memory since they both have their own memory manager.
The solution is to have the dlls and the exe share the VCL library and the memory manager. I am not a BCB developer, but a Delphi developer. In Delphi we would just use the rtl and the vcl as runtime packages. Maybe you could do the BCB equivalent.
A DLL has its own TApplication object.
to provide uniform key handling. when the DLL Loads.
assign the DLL::TApplication to the EXE::TApplication
Be sure to do the reverse on exit.
--
Michael