Hi.
How can I disable or grayed-out the 'X' button that closes a simple dialog ??
I know how to do it with the Minimize/Maximize buttons, i.e.: WS_MINIMIZEBOX/WS_MAXIMIZEBOX, but how to do it with the 'Close' button - that's my question.
Thanks.
Printable View
Hi.
How can I disable or grayed-out the 'X' button that closes a simple dialog ??
I know how to do it with the Minimize/Maximize buttons, i.e.: WS_MINIMIZEBOX/WS_MAXIMIZEBOX, but how to do it with the 'Close' button - that's my question.
Thanks.
The 'X' button is standard. I don't think you can gray it, but you can disable it's functionality. Override the 'OnClose' and do nothing in it.
Couple of ways of doing it:
1. Remove Close item from a system menu after main window is created, before main window shows. The ID for Close is SC_CLOSE.
2. Register own window class for a main window. Specify CS_NOCLOSE as class style.
3. Modify main window’s class style using SetClassLong and GCL_STYLE flag by adding CS_NOCLOSE.
Approach 1 is the easiest for a dialog window.
Here is the way I do it....
In OnInitDialog function:
CMenu* pSysMenu1 = GetSystemMenu(FALSE);
if (pSysMenu1 != NULL)
{
//disable the X
pSysMenu1->EnableMenuItem (SC_CLOSE, MF_BYCOMMAND|MF_DISABLED);
}
Well,
Disabling menu item suggest that it can be enabled, therefore is confusing; removing it seems more appropriate.
Removing SC_CLOSE menu will disable close button.
HOWEVER I have just tested it and in windows Vista, both actions will be needed: disabling first and removing next.
Removing SC_CLOSE alone, will not render disabled button even though it does not close window.
Just my two pennies on this one.. I think you should have really good reasons for disabling/removing the "x" on the system menu. That is standard windows behaviour, and you should try your very best to conform to the standard whenever you can. Of course you might have good reasons for your requirement, but you have not said anything about it. So in my opinion, in most cases, this is not user-friendly design.
Also it would be horrible to have the "x" disabled, only acceptable solution would be to remove the item from the menu.
Thanks you all for answering, but the trick with SC_CLOSE is for menus/MDI architecture, I have a simple dialog.
for some reason the CS_NOCLOSE doesn't work for me, this is what I do:
doesn't seem to work....Code:BOOL CCustomizedMessageBox::OnInitDialog()
{
DWORD dwStyle = GetWindowLong(m_hWnd, GWL_STYLE);
dwStyle |= CS_NOCLOSE;
// execute new style.
SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);
CDialog::OnInitDialog();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
any ideas ?!?
Thanks.
Ok, I've found all I was looking for - Thanks to everybody !!
:-)
how do you disable the 'X' close button then?
I tried
pSysMenu->EnableMenuItem (SC_CLOSE, MF_BYCOMMAND|MF_DISABLED);
but all it does it gray out the 'X' close button but not removing it from title bar
any ideas?
I have one reason for similar functionality of "greying" out the On close button, because my Modal Dialog crashes when I close it during some processing is happening in the background like " progress bar updates on my dialog box" , Edit box updates on my dialog box" , Other applications running which I had called from this application using "Shell execute:"
Any idea how to solve this crash issue. I tried few methods like disabling the progress bar and edit box updates but not working.
Are you handling the close message from the Modal Dialog?
yes. I am handling it in the function onClose();
One more peculiar observation I found was everything goes smooth if I dont close the Dialog till the end.
it crashes only If I close it during the processing of data is happening.
I am killing the applications which I had opened in OnClose() function.
If you are handling the modal dialogue close command, then you have an error in logic as Victor says in post #13. Whatever your code is doing for the modal dialogue close command is not correct. You should be able to debug/trace your modal dilogue close code and find the source of the 'crash' during this code.
As of now I am managing to "greying" out the close button of dialog box till my processing is completed.Once everything is done/or if intermediate error happens then I am enabling the "close" button so that user can exit the dialog window.
And what about closing the modal dialog using ENTER, ESCAPE, Ctrl+F4?
Is your processing in a thread, or just functions inside the dialog?
Disabling the close button isn't very user friendly. It would be better to interrupt your processing when the close button is pressed, then close the dialog.
Your debugger could likely assist you in determining why it is crashing.
Also that worker thread calls 2 console application s via Shellexecute which do the processing
It sounds like your modal dialog close code isn't properly allowing/signalling threads/processes to terminate cleanly - and waiting until they are. But as Victor says in post #24, this is guesswork without knowing much more detail re the application architecture etc - and you should never guess when coding! :eek:
Are your separate worker thread(s) directly updating the UI?
So, the dialog goes away and some worker thread then tries to update some non-existent UI element and promptly dies.
This is generally regarded as being a big no-no.
https://stackoverflow.com/questions/...ws-thread-safe
https://docs.microsoft.com/en-us/cpp...s?view=vs-2019
That it crashes when you close the dialog could just be the tip of a very large iceberg.
You need to create some inter-thread messaging system, where your worker thread sends say a "progress bar 1 = 20%" to the main UI thread, and the main UI thread itself does the update (and can also check that the dialog still exists).
What other multi-thread sins have you committed, just waiting to come back and bite you at some future time? Maybe your worker threads are busy writing into data structures that your main thread is busy reading from.
You need a PLAN (seriously!) before you add threads to existing code. Every shared function with a side-effect and every bit of shared data needs thinking about. You need a properly designed ownership and responsibility model before you even reach for the keyboard to type in some code. If you're not familiar with all this, then you have lots of studying to do.
If you're up to C++11, then https://en.cppreference.com/w/cpp/thread
Otherwise, your platform API, https://docs.microsoft.com/en-us/win...tion-functions
To be honest, if your code is under some kind of source control, and this "add threads" was a recent change, then I'd definitely suggest creating another branch from your last stable single thread version and starting again.
But if the change was months ago, merged with many other unrelated changes, or you have NO source control, then you really do have your work cut out. The rat's nest of race conditions you've created for yourself will be hard to remove completely.
It sounds like a bad design... :(
You should access your dialog control only from within the main UI-thread this dialog belongs to. Check it out: Using Worker Threads
To avoid that I moved my Progresscontrol and Edit box updates from worker thread to my OnTimer() function of the main dialog box but still it was crashing to some other places where CString's were handled( by the other applications called using SHellExecute from the worker thread - for which I dont have control over).
Now I have removed the worker thread itself from my code and doing everything in the main thread of CDialog itself. But the dialog window freezes now when the processing is happening and when the user click on Onclose ( X) button it will respond later but not crashing!
Thanks for the response VictorN and Salem_C.
In case of any further comments from the users and I may need to use at a worker thread at any cost will try to study in deep and see to resolve that issue.
This article may be of interest http://www.flounder.com/workerthreads.htm
As GCDEF said in post #32, in your processing code - often as part of a loop that takes time, or between different parts of the processing code. The message pump is there to ensure that windows messages are processed and hence that the UI remains 'responsive' during long periods of processing.
Learn how to do proper multithreaded programming. The work goes into a secondary thread and it updates the main ui thread using postmessage. The story has been the same for the past 25 years.