mity / mctrl

C library providing set of additional user interface controls for Windows, intended to be complementary to standard Win32API controls from USER32.DLL and COMCTL32.DLL.
http://mctrl.org
235 stars 52 forks source link

Unable to create chart from dialog template in memory #35

Closed schnufff closed 10 years ago

schnufff commented 10 years ago

Hi Mity, at first, thanks for your work: Exactly what I was looking for!

When creating the chart dialog using DLGTEMPLATE and DLGITEMTEMPLATE (without EX), all controls except the chart are created. I guess its related to the WindowClass "mCtrl.chart". Using a resource file, everything works.

Is this the right place to discuss the topic with you?

All the best schnufff

mity commented 10 years ago

Sure, it is the right place. Just a few assorted ideas:

(1) In the end, the control is always created the same way via CreateWindow[Ex](). Actually all the CreateDialog[Indirect][Param]() and DialogBox[Indirect][Param]() just interpret the template and call CreateWindow[Ex]() for the dialog (the parent window) and then for each template item (child windows). So I guess there is a bug rather on the application side rather then in mCtrl.

(2) Do you call mcChart_Initialize() before the attempt to create the dialog? Does it succeed?

(3) AFAIK, by default all the Win32 dialog creation functions fail if they are unable to create any control from the template resource (unless dialog style DS_NOFAILCREATE is used). Then the last CreateWindow() function it internally calls (and fails) should set the error via SetLastError(). I.e. calling GetLastError() could provide some hint what's going wrong.

(4) Do you use DS_NOFAILCREATE? If not, then I deduce (from the fact that the rest of the dialog was created) there is something wrong with your template or template item (i.e. CreateDialogIndirect() did not even try to create this control), or that the control was actually created but it has just an empty contents. That could happen, for example, if you do not provide any data to show in it (and no window text as the chart title).

It would also be helpful to specify Windows and mCtrl version you are using. Perhaps you could even provide some relevant code exhibiting the issue?

schnufff commented 10 years ago

Wow, you are fast. I am using mCtrl0.96 under Win7x64 and VS2010. mcChart_Initialize() is successfully and using mcCreateDialogParamW with a rc-file works as expected and shows an empty chart with the given title. Using below function, which constructs the DlgTemplate in memory , shows the dialog, the OK-button, but no empty chart. As the OK button is shown, I think the template itself is OK.

I managed to include the mCtrl sources into my project and the debug output shows a "mcBufferedPaintInit: Stub [E_NOTIMPL]

HWND lcCreateChart(HINSTANCE hInstance, HWND hWndParent, DLGPROC lpDialogFunc){ HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; int nchar; HWND ret;

hgbl=GlobalAlloc(GMEM_ZEROINIT,2048); if(!hgbl) return NULL;

lpdt=(LPDLGTEMPLATE)GlobalLock(hgbl); //define the dialog lpdt->style= DS_NOFAILCREATE | DS_MODALFRAME |DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_SIZEBOX; lpdt->x=0; lpdt->y=0; lpdt->cx=200; lpdt->cy=100; lpdt->cdit=2,

lpw=(LPWORD)(lpdt+1); lpw++=0; //no menu lpw++=0; //predifined dialog class

lpwsz=(LPWSTR)(lpw); nchar=MultiByteToWideChar(CP_ACP, 0, "My Dialog", -1, lpwsz, 50); lpw+=nchar;

//----------------------- // Define an OK button. //----------------------- lpw = lpwAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE)lpw; lpdit->x = 180; lpdit->y = 80; lpdit->cx = 20; lpdit->cy = 20; lpdit->id = IDOK; // OK button identifier lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;

lpw = (LPWORD)(lpdit + 1); lpw++ = 0xFFFF; lpw++ = 0x0080; // Button class

lpwsz = (LPWSTR)lpw; nchar = MultiByteToWideChar(CP_ACP, 0, "OK", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // No creation data

//----------------------- // Define scatter chart //----------------------- lpw = lpwAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE)lpw; lpdit->x = 5; lpdit->y = 5; lpdit->cx = 180; lpdit->cy = 80; lpdit->id = IDC_CHART_SCATTER; lpdit->style = MC_CHS_SCATTER | MC_CHS_DOUBLEBUFFER; lpdit->dwExtendedStyle = WS_EX_STATICEDGE;

lpw = (LPWORD)(lpdit + 1); lpwsz = (LPWSTR)lpw; nchar = MultiByteToWideChar(CP_ACP, 0, "mCtrl.chart", -1, lpwsz, 50);lpw+=nchar; //wcscpy(lpwsz,MC_WC_CHART); lpw += (wcslen(MC_WC_CHART)+1)*2;

lpwsz = (LPWSTR)lpw; nchar = MultiByteToWideChar(CP_ACP, 0, "Scatter chart", -1, lpwsz, 50); lpw += nchar;

*lpw++ = 0; // No creation data

GlobalUnlock(hgbl); ret = mcCreateDialogIndirectParamW(hInstance,(LPCDLGTEMPLATE)hgbl,hWndParent,lpDialogFunc,0,0);

GlobalFree(hgbl); return ret; }

mity commented 10 years ago

I can see two (potential) issues in your code:

I tried to compile the code with these things fixed and it works for me.

BTW, issues with window style or dialog geometry (e.g. control outside the parent window) can easily be observed with a tool like WinSpy or WinSpy++ (see http://www.catch22.net/software/winspy-17).

schnufff commented 10 years ago

Hi Mity, I dont know why WS_VISBLE was not required using the rc-file, but is using the in-memory templates. But this was the (trivial) solution. Thank you very much for your support.

All the best schnufff

mity commented 10 years ago

Because resource compiler adds some styles automatically when compiling the resource script.

neduddgi commented 6 years ago

nchar should be incremented: lpw += nchar +1;