How do I make a Win32 API button selected programatically? - winapi

I have a button, if i were to say click a checkbox, it should then give one of two buttons focus.
I am not sure how to use BM_SETSTATE - if that is the way to do it.
// snip...
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_CHECK:
if (IsDlgButtonChecked(hDlg, IDC_CHECK))
{
EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
EnableWindow(GetDlgItem(hDlg, IDCANCEL), TRUE);
BM_SETSTATE // ... ??
}
else
// ... snip
any help is greatly appreciated! thanks much!

I'm not sure if you understand exactly what you're asking, but maybe.
The highlight state indicates whether the button is highlighted as if the user had pushed it.
It does not indicate whether the button has focus nor does it indicate whether the button is checked or not.
If you really want to do this though, use the Button_SetState macro.
Just in case:
If you want to set the check state on a button use the Button_SetCheck macro.
If you want to set the focus on a button use the SetFocus Win32 API.
Note: Above I mentioned a couple macros, you can instead use SendMessage and pass the appropriate message as documented on the message in MSDN.

To make a button default in win32 (which i guess is your question) can simply be done by sending the button a BM_SETSTYLE message with BS_DEFPUSHBUTTON as the WPARAM...
HWND hwndButton = CreateWindow("button", "OK", WS_VISIBLE |...);
SendMessage(hwndButton, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
Hope this helps... ;-)

Related

fire event after mouse moves form - FMX C++

I want to run a block of code after my form has been moved on the screen by the traditional "left-mouse down on caption bar and drag to new spot". OnMouseUp only works on the form itself, not for mouse click on the title bar.
This is C++ and Win32 app.
thanks,
russ
UPDATE 1: Showing code i implemented based on Remy's answer. I implemented his code from that other post and then added another item to the switch(uMsg) to catch the WM_MOVE message. This didn't work.
case WM_MOVE:
{
ShowMessage("Moved");
}
UPDATE 2: I changed the above from WM_MOVE to WM_EXITSIZEMOVE based on Remy's comment and it works great now. Fires 1 time when i get through moving the form.
case WM_EXITSIZEMOVE:
{
ShowMessage("Moved");
}
Just what i wanted.
FireMonkey does not natively support what you are asking for. You will have to manually subclass the Form's HWND (see this answer) to intercept messages like WM_MOVING, WM_MOVE, WM_ENTERSIZEMOVE, WM_EXITSIZEMOVE, etc.

How to simulate modal dialog UI behaviour in a modeless dialog?

Is there an easy way to display a dialog modelessly while retaining the UI blocking a modal dialog provides?
I want to stop a user interacting with other dialogs/controls when the dialog is shown, but let the application carry on running. Is there a way to set a dialog as "exclusive focus" or something like that?
No, there is no easy way to do what you want.
If you really want to go the route you describe, I recommend first reading the whole 'modality' series on Raymond Chen's blog. First installment is on http://blogs.msdn.com/b/oldnewthing/archive/2005/02/18/376080.aspx .
However, this seems like an instance of the XY problem. What is it that you are trying to do? Get the main application to keep updating itself? If so, I think (with the information we are given) that calling AfxPumpMessage() will do what you want. Or do you want to continue processing data in the main application? Then you'll save yourself a world of hurt by using a worker thread.
Untested, but you can try do disable the owner window (the app. main window), create a modeless dialog, and then, when the dialog is closed, enable it again:
To disable the main window:
AfxGetMainWnd()->EnableWindow(FALSE);
To create the modal/non-blocking dialog:
dlg->Create(resId)
And to enable it again, on the OnClose event, or similar:
AfxGetMainWnd()->EnableWindow(TRUE);
There may be other details in a modal dialog that I'm not aware of. If you are willing to investigate, read the source code of MFC's CDialog::DoModal(). If I remember correctly, this MFC function simulates a modal-blocking dialog using the modeless Win32 API CreateDialog*() in order to implement global accelerators, hooks, messages and the like.
Here is possible answer to your question:
You could disable all the other controls in the application then re-enable them after the dialog has finished.
Use this callback
BOOL CALLBACK EnableDisableAllChildren ( HWND hwnd, LPARAM lp )
{
::EnableWindow ( hwnd, (BOOL)lp );
return TRUE;
}
With a Call to
EnumChildWindows ( HWNDToYourApp, EnableDisableAllChildren, true );
Do Modaless Dialog
EnumChildWindows ( HWNDToYourApp, EnableDisableAllChildren, false );
Something different to think about.

Change cursor on a win32 label

I want to change the mouse cursor for only one label. If I use SetClassLong the cursor for all labels is changed, I was told that I should use SetWindowLong as it is stated [here][1] but for some reason the mouse cursor doesn't change.
I am using a simple DialogBox.
Edit:
Sorry, if I didn't include my code. It was late and I was tired.
As recommended I will post the answer below.
Thanks to #Potter. I somewhat found the answer for changing the cursor for a win32 label control:
Do as the answer to this question says, you will have something like this.
case WM_SETCURSOR:
if((HWND)wParam == GetDlgItem( hWnd, 1014)) {
SetCursor(LoadCursor(NULL, IDC_HAND));
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, TRUE);
return TRUE;
}
In the properties of the control, make sure to set Notify to True.

Win32 custom message box

I want to make a custom message box. What I want to customize is the button's text.
MessageBoxW(
NULL,
L"Target folder already exists. Do you want to overwrite the folder?",
L"No title",
MB_YESNOCANCEL | MB_ICONQUESTION
);
I'd like to just change the buttons text to Overwrite, Skip, Cancel.
What's the most simple way?
I have to make this as having same look and feel with Windows default messagebox.
As said by others, a typical way is to create a dialog resource and have a completely independent dialog, which GUI you need to design in the way that it looks like standard dialog (to meet your request for feel and look). If you want to accept text messages, you might probably need to add code which resizes the window appropriately.
Still, there is another option for those who feel like diving into advanced things. While MessageBox API does not offer much for fint tuning, you still have SetWindowsHookEx in your hands. Having registgered the hook, you can intercept standard MessageBox window procedure and subclass it in the way you like.
Typical things include:
changing button text
adding more controls
adding timed automatic close
Hooking standard window can do all of those.
UPD. Hey, I realized I have some code with SetWindowsHookEx to share: http://alax.info/blog/127
You could create an own dialog. Or you could use a window hook as described in this article.
An archived version of the article can be found on web.archive.com.
Make a dialog resource (with a GUI editor, or by hand) and call DialogBox on it. There's no way to alter MessageBox behaviour, other than what's supported by its arguments.
That said, your message box can very well use stock Yes/No options.
The task dialog functionality introduced in Vista does exactly what you want and follows the prevailing system theme. However, if you have to support XP, then this will be of little comfort to you.
I know this question is old, but I just stumbled upon it now.
I would like to expand the other answers in regards to using a TaskDialog instead of a MessageBox. Here's a concise example of using a TaskDialog to do precisely what was asked; change the button's texts:
const TASKDIALOG_BUTTON buttons[] = { {IDYES, L"Overwrite"}, {IDNO, L"Skip"}, {IDCANCEL, L"Cancel"} };
TASKDIALOGCONFIG taskDialogConfig = {
.cbSize = sizeof(TASKDIALOGCONFIG),
.pszMainIcon = TD_WARNING_ICON, // TaskDialog does not support a question icon; see below
.pButtons = buttons,
.cButtons = ARRAYSIZE(buttons),
.pszWindowTitle = L"No title",
.pszContent = L"Target folder already exists. Do you want to overwrite the folder?"
};
TaskDialogIndirect(&taskDialogConfig, NULL, NULL, NULL);
Some noteworthy things:
You need to use TaskDialogIndirect, not the basic TaskDialog function
when not specifying a parent window, the icon specified in pszMainIcon is displayed in the title bar as well
There is no equivalent to the MessageBox's MB_ICONQUESTION, quoting a quote from this forumpost: Don't use the question mark icon to ask questions. Again, use the question mark icon only for Help entry points. There is no need to ask questions using the question mark icon anyway—it's sufficient to present a main instruction as a question.
checking which button was selected would have to be done by passing a pointer to an int as the second argument of TaskDialogIndirect and checking its value on return (the documentation should be pretty clear)
Here is a small open source library that allows you to customize Message Boxes. Developed by Hans Ditrich.
I have successfully used it in another POC that allows embedding a custom icon in such MessageBox that can be called even from a Console application.
I should also point to the Task Dialog. Here is an example of using it:
int nButtonPressed = 0;
TaskDialog(NULL, hInst,
MAKEINTRESOURCE(IDS_APPLICATION_TITLE),
MAKEINTRESOURCE(IDS_DOSOMETHING),
MAKEINTRESOURCE(IDS_SOMECONTENT),
TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON,
TD_WARNING_ICON,
&nButtonPressed);
if (IDOK == nButtonPressed)
{
// OK button pressed
}
else if (IDCANCEL == nButtonPressed)
{
// Cancel pressed
}

Hiding a control in Windows

I can't figure out how to hide a child window (a control), more specifically a GroupBox and a PushButton. I thought ShowWindow() with SW_HIDE as the second parameter would do the job, but it simply doesn't work. Yet SW_SHOW works just fine. I have the correct window handle for both controls, so that's not the issue.
I googled and all I could find was people asking how to hide dialogs, not controls. Either that or MFC-based applications, which doesn't apply here.
I'm using pure Windows API, no MFC.
What am I getting wrong?
EDIT: More info: I'm writing some simple class wrappers for WinApi controls. The WindowsControl class has, along other methods, the following methods for showing and hiding the Control:
void Show() {
ShowWindow(this->_hWnd,SW_SHOWNOACTIVATE);
}
void Hide() {
ShowWindow(this->_hWnd,SW_HIDE);
}
Every control inherits from WindowsControl.
This image has the window layout so you understand exactly what I'm doing: http://i.stack.imgur.com/PHQnH.png
When the user clicks inside the "Chipset" Static control, it'll load information for a given Tile (which is stored in an array, but that's irrelevant). Depending on the setting, it'll hide the "Edit bitwall" button on the left and show the empty GroupBox behind it or viceversa.
Just to be clear this isn't something wrong with my windows api wrappers, I am getting the correct HWND. Though ShowWindow might not be able to be called from a Window Procedure that isn't the parent's (that'd be weird).
EDIT2: Using C++ with Visual Studio 2008, no MFC, no WTL, no CLR, no .NET
EDIT3: I'll post even more code so it's easier
Inside the static's window procedure, I handle WN_LBUTTONDOWN like this:
case WM_LBUTTONDOWN: {
...
update_tiledata(c, l)
void update_tiledata(GroupBox * c, ListView* l ) {
...
if (chp_copy.Tiles[selectedTile].Pass() == PT_BITWALL) {
c->Controls(CTL_BTNEDITBIT)->Show();
c->Controls(CTL_FRPHOLD)->Hide();
} else {
c->Controls(CTL_FRPHOLD)->Show();
c->Controls(CTL_BTNEDITBIT)->Hide();
}
update_edits();
}
The ommited code does nothing to affect the classes, as I said before, ShowWindow with SW_HIDE IS getting called, with the correct HWND, but nothing is happening.
A control in a Window or dialog can be hidden using
ShowWindow(hControlWin, SW_HIDE);
In a dialog you can retrive the controls window handle by calling
GetDlgItem(hDlg, < CtrlID >);
Typically you write something like:
ShowWindow(GetDlgItem(hDlg, 2), SW_HIDE);
It would be helpful if you give more information and some code: How did you create the controls? What language, compile and framework did you use?
I think the function call you want is EnableWindow I have used this before to disable a button on a form. You will need to get an handle to the Window (object) first though so you might want to use EnumChildWindows to iterate through all the controls to find the one you want.

Resources