I am not able to create MFC dialog, when the resources are loaded from another language. The dialog gets created if the language is English. I have added a string in the dialog, CLASS "Singleton Application". And in the code, i do a RegisterClass with this class name. Also i am setting the correct AfxSetResourceHandle. If i remove this "CLASS" entry, i am able to create the dialog in other languages. Any pointers would be helpful.
Related
I'm using raw Win32 and C++ for a project. As I understand it, I am able to superclass Windows controls by retrieving the class information, replacing the procedure, then registering this as a new class and using it when creating a new window. Subclassing is done by replacing the window's procedure after the window is created. The advantage of superclassing is that you are able to process messages before CreateWindow() returns.
I'm looking to see if it's possible to superclass a dialog box created with CreateDialog() because I'd like to use a resource file for the dialog layout. The problem is that I don't know how I would provide my superclass when I create a dialog box. Is it even possible? Any idea how MFC handles this?
If you use an extended dialog box template to create your dialog, you can specify a custom window class as part of the DLGTEMPLATEEX definition.
The dialog manager will create and layout your dialog as normal, and call your window procedure for any dialog messages. You can use the DefDlgProc function to obtain default processing for any dialog messages you don't want to handle yourself.
In ResourceHacker, when you open an executable (windows), you can see identifiers associated with dialogs. Does anyone have an idea from where they come? I mean, how can I do the same in my C++ program to get the ID from a HWND?
BTW, GetWindowLong(hwnd, GWL_ID) returns 0.
Thanks
The GetWindowLong(hwnd, GWL_ID) returns the identifier of a control in a dialog, but it cannot be used for the dialog itself, because dialogs simply don't have identifiers.
The identifiers associated with dialogs are actually used to refer to the resource blob itself, not to the window. They are used to create the dialog (see CreateDialog().
Once the dialog is created there is no connection to the original template or to that identifier. Actually there is no use for that ID, the dialog is simply identified by its HWND. Note that you can create several different dialog using the same dialog resource.
These identifiers are assigned (usually) sequentially by the resource editor, or manually if you create the resources by hand.
For more insight on the topic you can read about the CreateDialogIndirect() function, that creates a dialog without using a resouce.
Here you find a good answer:
http://blogs.msdn.com/b/oldnewthing/archive/2005/07/08/436815.aspx
It's like asking, "Given a plate of food, how do I recover the
original cookbook and page number for the recipe?" By doing a chemical
analysis of the food, you might be able to recover "a" recipe, but
there is nothing in the food itself that says, "I came from The Joy of
Cooking, page 253."
So the answer is that there is no way provided by Microsoft to obtain the dialog ID. They could have easily stored it anywhere to make it available, but they did not.
But there would still be a way to do it, although it is not bulletproof. You could:
1.) Get the creator file of the dialog via GetWindowModuleFileName()
2.) Load this Exe or Dll via LoadLibraryEx(..., LOAD_LIBRARY_AS_IMAGE_RESOURCE)
3.) Enumerate all RT_DIALOG resources in the Exe or Dll via EnumResourceNames() where the dialog ID is in the name: ResourceName = MAKEINTRESOURCE(IDD_DIALOG_ID)
4.) Create each enumerated dialog invisibly via LoadResource(), LockResource(), CreateDialogIndirect() but without showing the dialog with ShowWindow().
5.) Enumerate the child controls in each dialog via EnumChildWindows() and compare them to your dialog.
6.) Release all handles and destroy the dialogs.
It is not very probable that there are two identical dialogs in a Exe/Dll file. But the problem is that in WM_INITDIALOG the programmer may eliminate (destroy) or add or modify child controls. So your search algorithm would have to be fault tolerant. This would be possible by counting the congruency between each dialog from the resources and your dialog. You could count for how many child controls the ID (GetDlgCtrlID())and class name (GetClassName()) match. (e.g. Class="BUTTON" and ID = 311") While a programmer can easily change the text of a control or move it around, changing the ID is not very probable and does not make much sense and changing the class of a child control is even impossible.
As I said: It is not bullet proof, but you will find the ID of the resource that has most probably been used to create the dialog.
Be aware that not all dialogs come from a Microsoft resource.
They can be created by a GUI framework that uses its own type of templates. In this case you will never find the Dialog ID because it simply does not exist.
In ResourceHacker, when you open an executable (windows), you can see identifiers associated with dialogs. Does anyone have an idea from where they come? I mean, how can I do the same in my C++ program to get the ID from a HWND?
BTW, GetWindowLong(hwnd, GWL_ID) returns 0.
Thanks
The GetWindowLong(hwnd, GWL_ID) returns the identifier of a control in a dialog, but it cannot be used for the dialog itself, because dialogs simply don't have identifiers.
The identifiers associated with dialogs are actually used to refer to the resource blob itself, not to the window. They are used to create the dialog (see CreateDialog().
Once the dialog is created there is no connection to the original template or to that identifier. Actually there is no use for that ID, the dialog is simply identified by its HWND. Note that you can create several different dialog using the same dialog resource.
These identifiers are assigned (usually) sequentially by the resource editor, or manually if you create the resources by hand.
For more insight on the topic you can read about the CreateDialogIndirect() function, that creates a dialog without using a resouce.
Here you find a good answer:
http://blogs.msdn.com/b/oldnewthing/archive/2005/07/08/436815.aspx
It's like asking, "Given a plate of food, how do I recover the
original cookbook and page number for the recipe?" By doing a chemical
analysis of the food, you might be able to recover "a" recipe, but
there is nothing in the food itself that says, "I came from The Joy of
Cooking, page 253."
So the answer is that there is no way provided by Microsoft to obtain the dialog ID. They could have easily stored it anywhere to make it available, but they did not.
But there would still be a way to do it, although it is not bulletproof. You could:
1.) Get the creator file of the dialog via GetWindowModuleFileName()
2.) Load this Exe or Dll via LoadLibraryEx(..., LOAD_LIBRARY_AS_IMAGE_RESOURCE)
3.) Enumerate all RT_DIALOG resources in the Exe or Dll via EnumResourceNames() where the dialog ID is in the name: ResourceName = MAKEINTRESOURCE(IDD_DIALOG_ID)
4.) Create each enumerated dialog invisibly via LoadResource(), LockResource(), CreateDialogIndirect() but without showing the dialog with ShowWindow().
5.) Enumerate the child controls in each dialog via EnumChildWindows() and compare them to your dialog.
6.) Release all handles and destroy the dialogs.
It is not very probable that there are two identical dialogs in a Exe/Dll file. But the problem is that in WM_INITDIALOG the programmer may eliminate (destroy) or add or modify child controls. So your search algorithm would have to be fault tolerant. This would be possible by counting the congruency between each dialog from the resources and your dialog. You could count for how many child controls the ID (GetDlgCtrlID())and class name (GetClassName()) match. (e.g. Class="BUTTON" and ID = 311") While a programmer can easily change the text of a control or move it around, changing the ID is not very probable and does not make much sense and changing the class of a child control is even impossible.
As I said: It is not bullet proof, but you will find the ID of the resource that has most probably been used to create the dialog.
Be aware that not all dialogs come from a Microsoft resource.
They can be created by a GUI framework that uses its own type of templates. In this case you will never find the Dialog ID because it simply does not exist.
I need to create some dynamic menus in a VS2010 SDI application I'm writing. I've seen this, but don't really understand it
Dynamic menu using mfc
At the moment, I've no idea how to even use GetMenu to get a handle to the menu from my Doc file. I'm trying this, but it says GetMenu doesn't take zero arguments, even though many examples I've seen clearly show this.
CMenu *menu = GetMenu();
menu->AppendMenu(MF_STRING, ID_HIDE, _T("Text"));
All I want to do is add a list of files underneath a sub-menu, selected from a database (hence the dynamic part), so a user can select the one they want to work on.
Thanks,
James
If you're calling GetMenu from within a window class derived from CWnd, you'll be calling CWnd::GetMenu and it will not require a window handle. If you're calling it from anywhere else you will get ::GetMenu(HWND) and you will need to pass a window handle. You can get the handle from any CWnd object with its m_hWnd member or by calling GetSafeHwnd() on it.
I'm fairly new to VC++ and MFC, so bear with me. I have created a new dialog, and I want to figure out how to display it when the user clicks a button.
I have not create a class or header file for the dialog -- I tried using the class wizard, but it pretty much sucked and didn't work. That, or I was doing something wrong. Either one is equally as likely if you ask me.
So what steps do I need to take when creating the source/header files and getting the dialog to launch/display? It is a modal dialog.
CLARIFICATION: I understand that I need to create an instance of the dialog class, then just call DoModal() on it, but I'm not sure how to create the class file (with and/or without the wizard).
Right click the project and select
Add | Resource...
Select Dialog under Resource
type and click New.
Select Project | Add Class...
Enter CMyDialog for the Class
name, CDialog for the Base class
and Click Finish.
Read more: How to Make MFC Dialog Boxes
Seems to me you can make the button click just create a new instance of the dialog object and activate it. You'll probably have to keep a reference to the dialog so it doesn't get killed when the button action fxn returns it doesn't get garbage collected..