WinAPI How to Apply Edit field text change? - winapi

I'm working with 3d party application. Changing a text in Edit control using
SendMessageW(m_edit_handle,WM_SETTEXT,0,str_address);
And it works fine.. It changes visually in the window. But once I click a button (also programmatically) it works as there is a default value but not the one I set with SendMessageW.
Just wondering if after changing the text in Edit window I have to call some other method to force Windows to update the actual value in the field?

Depending on how the target app is coded, you may need to issue an EN_CHANGE notification to the Edit's parent window. Sending WM_SETTEXT will not send that notification, as it is meant to be sent when the user makes changes to the Edit's content, not when code does.
SendMessageW(m_edit_handle, WM_SETTEXT, 0, str_address);
SendMessageW(GetParent(m_edit_handle), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(m_edit_handle), EN_CHANGE), LPARAM(m_edit_handle));

Related

Is there any way to activate the Apply button from a print propery page with PrintDlgEx?

I have custom print property sheets/pages that have been added to the dialog displayed by PrintDlgEx. These property sheets are, of course, used to change additional options. The issue is that there does not appear to be any documented way to activate the Apply button from the property sheet's dialog function, or anywhere for that matter. This seems to be a huge omission on Microsoft's part.
Is there any "official" way to change the Apply button's state? If not, are there any possible workarounds?
Is there any "official" way to change the Apply button's state? If not, are there any possible workarounds?
Not directly, no. You would have to retrieve the button's HWND manually an then manipulate it as needed.
use SetWindowHookEx() to install a local WH_CBT hook for the thread that is calling PrintDlgEx(). The dialog's HWND will be available as a parameter of the callback function when it receives a HCBT_ACTIVATE notification. Then you can locate the Apply button's HWND within the dialog (use Spy++ or similar tool to get details about the button, then have your code use GetDlgItem() or FindWindowEx() to get the button's HWND). Be sure to call UnhookWindowsHookEx() after PrintDlgEx() exits (or at least after you are done using the button HWND).
use SetWinEventHook() to register for EVENT_OBJECT_CREATE, EVENT_OBJECT_SHOW, and/or EVENT_SYSTEM_DIALOGSTART notification(s) for the thread that is calling PrintDlgEx(). The dialog and button HWNDs will be available as a parameter of the callback function. Be sure to call UnhookWinEvent() after PrintDlgEx() exits (or at least after you are done using the button HWND).
Once you have the button's HWND, you can do whatever you want with it. It is a standard button control, so any standard button message/function can be used with it.
A more close to "official" way is to call PropSheet_Changed().
The way I get the property sheet dialog is to look at the source of PSN_ notifications sent to IPrintDialogCallback::HandleMessage(). Or you can use GetParent(GetParent(generalDialog)).
Once you call PropSheet_Changed() the Apply button will activate.
You're right, it seems to be a huge omission on Microsoft's part, as it's not a simple thing to code, but it's something that most people adding property sheets would need.
I can put some code up if anyone needs it.

How to stop event propagation despite WS_EX_NOACTIVATE?

I have a semi-transparent form (using AlphaBlend) that acts as an overlay. For the user to still be able to interact with the window below I have set WS_EX_NOACTIVATE on my form so all right and left clicks go through to the other window.
However I have a few clickable labels on my form. Clicking those and performing the appropriate action works fine since despite the WS_EX_NOACTIVATE flag the OnClick methods are called, but the click will (obviousely) also propagate to the other window, which I do not want in this case.
So, does anyone know how to "stop" the click being sent through to the window below in case I already handled it in my form ? Basically I would like being able to chose whether the click "belongs to me" and does not get propagated or whether the window below mine receives it.
As Rob explained, WS_EX_NOACTIVATE is not relevant here. Most likely you used WS_EX_TRANSPARENT and that made your window transparent to mouse clicks.
To get finer grained control of mouse click transparency, handle the WM_NCHITTEST message in your top level window. Return HTTRANSPARENT for regions that you want to be "click through". Otherwise return, for example, HTCLIENT.
Wm_ex_NoActivate should be irrelevant here. That just controls whether your window receives the input focus. Indeed, if you start with a scratch program and do nothing but change the extended window style, you'll see that when you click within the bounds of that program's window, the clicks are handled in the usual way, except that the window is never activated; programs behind that window do not receive any click events.
Therefore, to make your label controls eat click events instead of forwarding them to the windows behind them, you need to find out what you did to make them start forwarding those messages and simply stop doing that, whatever that is.

Auto resize a dialog control when parent window is resized WinApi

I am trying to show a web page in a dialog control. All is working fine till I maximize the parent window, the inner control with webpage retains its size and so a blank area is left at the side of window. I want to know is there any WS_* message or something I can use to auto resize control when we resize the main window. I am using resource hacker so may be there can be some trick I should know.
Any help is appreciated.
Thanks.
The application must perform the resize. And it does so when it receives a WM_SIZE message for the parent control.
You are not going to be able change this by modifying the resources in a pre-existing binary. You are going to need to write some code to respond to that message.
The way I'd try seeing as I've never tried to hack something like this in.
Would be to see if the web control had an anchors property.
Its should be being passed a wm-size message, it's just not doing anything with it.
If you anchor all four corners of the webcontrol it should resize relative to it's parent.
The other way this is done is through explicit code that handles a resize event, don't think you could hack that in very easily though.

Determine if the focused control is an Editable one?

Using pure Win32 API, how can I get the handle to the control that currently has the focus? And then how can I determine if it's a Text Box / Rich Text Box?
I'm trying to write a small macro keys program which will allow user to register new hot keys using the RegisterHotKey() function. Everything is working fine except that I don't want to violently call SetWindowText() or SendMessage(hWnd, WM_SETTEXT, 0, TEXT("Something")) without knowing whether the control is a text box or not.
Be noted that I want a handle to the control that currently has the focus, not the whole window the user is working on.

Tooltip only shows when running from source

I have a hierarchical flexgrid control with the ToolTipText property set, and when I run from source the tooltip displays as it should. But when I compile it and run that way, the tooltip doesn't display.
I've tried to remove anything listening to MouseMove in the hopes that that would fix it, and when I add some code to put the tooltip text into a message box, it appears to be set correctly. Can anyone think of why this would be happening?
Update: It appears that the problem arises when I host the grid inside another user control. E.g.: make container.ctl, which is just a blank control but with ControlContainer = True. Then make gridholder.ctl, which is a mshfg inside of a container.ctl. Lastly, embed gridholder.ctl into some form. Tooltips on the flexgrid don't appear to show up.
I'm interested to see how reproducible this is...
I haven't found a workaround for this issue yet, but I have a better idea of why it's happening after some testing and stepping through some of the VB6 runtime code in WinDBG.
The first interesting thing is that VB6 doesn't use the standard tooltip display mechanisms provided by Windows. For example, it doesn't use WM_NOTIFY messages to show/hide tooltips, or any of the other "standard" tooltip support described in the documentation explaining how tooltips work in Windows.
Instead, the VB6 runtime has its own way of managing and displaying tooltips. In principle, it's similar to in some ways to the standard Windows way of dealing with tooltips, but it's also different in a quite a few areas.
A breakdown of how VB6 does tooltips:
When a VB6 program starts, the runtime uses SetWindowsHookEx to install a mouse hook for the program's main thread.
The mouse hook intercepts all mouse messages sent to the program, in particular all WM_MOUSEMOUSE messages
Whenever the mouse hook runs, it calls an internal method in the VB6 runtime to get the object pointer (HCTL) of the control that the mouse is currently over top of. Note that this is an actual COM interface pointer, not a window handle.
It translates the HCTL to the corresponding window handle (HWND).
It checks to see if the mouse position is within that window's rectangle.
If so, it retrieves the ToolTipText property for the control. If this is not empty, it creates a tooltip window and displays the tooltip after a 700ms delay.
The problem with the MSHFlexGrid (and I imagine other controls that are not standard VB6 controls) is that this code doesn't retrieve the correct HCTL when you hover over the control and it's inside a custom container.
In that case, the code retrieves the HCTL of the custom container, not the HCTL of the MSHFlexGrid itself. Therefore, it retrieves the container's ToolTipText property (which is empty) and not the grid's ToolTipText, and therefore won't display a tooltip.
I'm not sure exactly why it does this, because as noted in the comments on your question, all of this works correctly if you use a PictureBox as your container.
I suspect the PictureBox has code to handle this correctly that is not included when you create your own container.
I'll update this answer with an actual workaround if I can find one. The only thing I can think right now is to somehow "sync" your container's ToolTipText property with the grid's ToolTipText property, so that when VB6 requests the container's ToolTipText, it will return the value of the grid's ToolTextTip property instead.
This is easier said than done, however, because ToolTipText is an extender property, and extender properties take precedence over properties that you write yourself that have the same name.
After a bit of research, I found what I think is the underlying problem. Your user control is not implementing any method for the controls to interact with. User Controls that are Container Controls need to implement the Extender functionality. These two links are the best I've found on the subject so far.
http://www.justvb.net/obook/ch7.htm#UsingtheExtenderObject
http://msdn.microsoft.com/en-us/library/aa733622(v=vs.60).aspx

Resources