|
Ugh, those hackercrackers controlling poor dialogs found with FindWindow...
Even I have not entirely got the point or even for fun or for sake of code digging, here is a solution.
Override CDialog::DoModal to modyfy DLGTEMPLATE structure passed to CreateDlgIndirect function.
Copy/paste the code from default CDialog::DoModal implementation then make some cosmetics.
Below is a trivial example which makes some assumptions, to simplify code and be easier to get the idea.
You must read carefully the DLGTEMPLATEEX structure documentation, focusing on menu and windowClass members that have variable length and modify my example to take care of each case (has a menu or not, and so on...).
- we have a DIALOGEX resource.
- the dialog has attached a menu with ID in the .rc file (not a name).
- a CLASS statement was inserted in .rc file, that we'll replace with a class name with the same length.
#include <AFXPRIV.H>
#include <AFXIMPL.H>
#define DELETE_EXCEPTION(e) do { e->Delete(); } while (0)
int CMyDialog::DoModal()
{
TRY
{
AfxHookWindowCreate(this);
DLGTEMPLATEEX* lpDlgTemplateEx = (DLGTEMPLATEEX*)lpDialogTemplate;
WCHAR* pClassName = ((WCHAR*)lpDlgTemplateEx
+ sizeof(DLGTEMPLATEEX) / sizeof(WCHAR)
+ 2 * sizeof(WORD) / sizeof(WCHAR));
wcscpy(pClassName, L"Tata Leone");
if (CreateDlgIndirect(lpDialogTemplate,
CWnd::FromHandle(hWndParent), hInst))
}
Of course "Mama Leone" is defined in resources CLASS statement, and "Tata Leone" is a registered class.
And of course the class name can be randomly generated or using a GUID.
Ovidiu Cucu
Microsoft MVP - Visual C++
-- modified at 5:41 Friday 30th June, 2006
|
|
|
|
|
En, Thank you very much for your new way to solve my trouble, but if I want to create modeless dialog, how to do that?
maybe override create() is not a practical way, because it will call "CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd, HINSTANCE hInst)" after some steps, but this function is not a virtual one.
BOOL CMainDlg::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
{
//omit some original code
//call function
HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);
HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG);
HGLOBAL hTemplate = LoadResource(hInst, hResource);
BOOL bResult = CreateIndirect(hTemplate, pParentWnd, hInst);
FreeResource(hTemplate);
return bResult;
}
BOOL CWnd::CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate,
CWnd* pParentWnd, HINSTANCE hInst)
{
//omit some original code
// create modeless dialog
AfxHookWindowCreate(this);
hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate, pParentWnd->GetSafeHwnd(),
AfxDlgProc);
//omit some original code
}
can you tell me how to do that? thank you very much.
virtual
|
|
|
|
|
How nasty! No virtual, no override...
Well, no problem. Write your own Create function as well:
class CMyDialog : public CDialog
{
BOOL Create(UINT nResID, CWnd* pParent)
{ return Create(MAKEINTRESOURCE(nResID), pParent);}
BOOL Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd);
};
#include <AFXIMPL.H>
BOOL CMyDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
{
ASSERT(HIWORD(lpszTemplateName) == 0 ||
AfxIsValidString(lpszTemplateName));
m_lpszTemplateName = lpszTemplateName;
if (HIWORD(m_lpszTemplateName) == 0 && m_nIDHelp == 0)
m_nIDHelp = LOWORD((DWORD)m_lpszTemplateName);
HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);
HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG);
HGLOBAL hTemplate = LoadResource(hInst, hResource);
ASSERT(hTemplate != NULL);
DLGTEMPLATEEX* lpDialogTemplate = (DLGTEMPLATEEX*)LockResource(hTemplate);
WCHAR* pClassName = ((WCHAR*)lpDialogTemplate
+ sizeof(DLGTEMPLATEEX) / sizeof(WCHAR)
+ 2 * sizeof(WORD) / sizeof(WCHAR));
wcscpy(pClassName, L"Tata Leone");
BOOL bResult = CreateIndirect((LPCDLGTEMPLATE)lpDialogTemplate,
pParentWnd, NULL, hInst);
UnlockResource(hTemplate);
FreeResource(hTemplate);
return bResult;
}
Ovidiu Cucu
Microsoft MVP - Visual C++
-- modified at 4:39 Sunday 2nd July, 2006
|
|
|
|
|
Thank you very much, I will do a test.
virtual
|
|
|
|
|
Can not open header file "AFXIMPL.H", so...
thanks.
|
|
|
|
|
You have to add the folder where AFXIMPL.H is situated
or easier remove #include <AFXIMPL.H> and define DLGTEMPLATEEX yourself, as follows:
#pragma pack(push, 1)
typedef struct
{
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
} DLGTEMPLATEEX;
#pragma pack(pop)
Ovidiu Cucu
Microsoft MVP - Visual C++
|
|
|
|
|
Thank you very much, let me try.
|
|
|
|
|
Thank you very much, let me try.
virtual
|
|
|
|
|
Thank you very much, but I have to ask a question about "Create", when the function "wcscpy(pClassName, L"seek")" is excuting, the memeory can not be written, that is to say, I can not change the class name, how to do? Thanks.
virtual
|
|
|
|
|
I have tested my examples and work wery well.
However, if you read again more carefully my previous posts you'll see that I have made some particular presumptions like
- we have a DIALOGEX resource.
- the dialog has attached a menu with ID in the .rc file (not a name).
- a CLASS statement was inserted in .rc file, that we'll replace with a class name with the same length.
If one of them is not respected, most possible you can have troubles.
There are just particular-case EXAMPLES, intended to show you the IDEA.
If you want to deal with all the cases and write a general function, dig deeper in DLGTEMPLATEEX structure documentation, as I already said and modify the code accordingly.
I can do that for you "solving all your homework", but I have not enough time now. And note that it's not for free, although costs only a dozen of beers...
Ovidiu Cucu
Microsoft MVP - Visual C++
|
|
|
|
|
Thanks a lot, the second presumption is not met, because I do not need a menu, so do you mean I have to attach a menu that I do not need in my .rc file? I am so sorry to disturb you again and again, if you can solve my problem completely, I will pay for your beers. ;P
virtual
|
|
|
|
|
Beers first!
Well, no menu, then lesser to skip.
WCHAR* pClassName = ((WCHAR*)lpDialogTemplate
+ sizeof(DLGTEMPLATEEX) / sizeof(WCHAR)
+ sizeof(WORD) / sizeof(WCHAR));
And don't forget to take a look in the .rc file to asure you have something like
IDD_DIALOG1 DIALOGEX DISCARDABLE 0, 0, 186, 95
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
CLASS "Mama Leone"
However, this is just a patch. As I already said, sweat a little and write a serious function taking care of every case.
Ovidiu Cucu
Microsoft MVP - Visual C++
|
|
|
|
|
OK, Beers is here.
I have done many tests, and then I found that "wcscpy(pClassName, L"Lama Leone");" can not excuted once I try to change the class name, the other way round, if I did not try to change the class name, this function can be excuted correctly. I think there may be some properties of the resource need be changed, but I do not know what properties should be changed and how. Thanks.
virtual
|
|
|
|
|
Hi,
I have a menu on a dialog box. There is an option called Grid , which which can be toggled. I want it to be checked/un-checked.
This is what I have done. It looks right to me. But it is not working.
void COption2::OnChartoptionsGrid()
{
IsGrid = 1- IsGrid;
}
void COption2::OnUpdateChartoptionsGrid(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(IsGrid);
}
Please help.
Fortitudine Vincimus!
|
|
|
|
|
if you look at the value of IsGrid when OnUpdateChartoptionsGrid gets called is the value as you expect it to be?
cje
|
|
|
|
|
Yes. It come 1 .
Even if I do not put
pCmdUI->SetCheck(IsGrid);
instead if I put
pCmdUI->SetCheck(1);
nothing happens
Fortitudine Vincimus!
|
|
|
|
|
|
Viorel. wrote: Are you sure your OnUpdateChartoptionsGrid handler is called by MFC?
Yes. I used the usual class wizard to call it.
Fortitudine Vincimus!
|
|
|
|
|
While I agree that your recommendation is a better solution (and more readable), what he has will work for toggling:
isGrid = 0;
isGrid = 1 - isGrid;
isGrid = 1 - isGrid;
isGrid = 1;
isGrid = 1 - isGrid;
isGrid = 1 - isGrid;
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
Are you sure this function is executed when you start the program, open the dialog and click on menu item?
In order to check it, put a breakpoint in OnUpdateChartoptionsGrid (or MessageBox("The function was called") if you are not familiar with debugging). I suppose the function is never executed, that's why it does not have any effect.
|
|
|
|
|
Viorel. wrote: Are you sure this function is executed when you start the program, open the dialog and click on menu item?
Yes! The function IS executed. I put a message box and checked for both. .Thats the terriple part. I added the code to make the grid appear/disappear. Every thing is working fine. Only the check is not appearing.
Fortitudine Vincimus!
|
|
|
|
|
TheinstruTara wrote: added the code to make the grid appear/disappear. Every thing is working fine. Only the check is not appearing.
but the code you would use to make the grid appear/disappear would be in
void COption2::OnChartoptionsGrid()
setting the check mark is supposed to be happening in
void COption2::OnUpdateChartoptionsGrid(CCmdUI* pCmdUI)
There is no default support for calling OnUpdate routines in dialog boxes, there are articles etc... on how to do it.
If you set a breakpoint on the line
pCmdUI->SetCheck(IsGrid);
do you break in to the debugger when your dialog loads?
cje
|
|
|
|
|
Yes. I does.
Fortitudine Vincimus!
|
|
|
|
|
then I guess that my only other suggestion would be to get a pointer to the CMenu object and call CheckMenuItem directly instead of going through the OnUpdate mechanism. Something is certainly strange here - my code uses pCmdUI->SetCheck without a problem. sorry I can't be more help
cje
|
|
|
|
|
then I guess that my only other suggestion would be to get a pointer to the CMenu object and call CheckMenuItem direclty instead of going through the OnUpdate mechanism. My code uses pCmdUI->SetCheck without problems so there is definately something not right going on. Sorry I can't be of more help
cje
|
|
|
|