windowswinapicontrolspropertysheet

Can I make a property sheet without resource script?


I'd like to add controls to a property sheet without resource script, rather using pure code. The reason for this I'd like to create a property sheet(mimicking C#'s property grid), calling C routines/WINAPI, from another language, binary-compatible to C; but I'd like to define everything with code, without need of a resource script. Is this possible or the way to go is write my own property-sheet-like, with underlying CreateWindow*() calls? (different approaches to do this are welcome, I'm new to WINAPI) which I suppose property sheet use behind the scenes


Solution

  • Found the solution! I found this post from Raymond Chen where he shows how do that.

    the main code goes like this:

    BOOL FakeMessageBox(HWND hwnd, LPCWSTR pszMessage, LPCWSTR pszTitle)
    {
     BOOL fSuccess = FALSE;
     HDC hdc = GetDC(NULL);
     if (hdc) {
      NONCLIENTMETRICSW ncm = { sizeof(ncm) };
      if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) {
       DialogTemplate tmp;
    
       // Write out the extended dialog template header
       tmp.Write<WORD>(1); // dialog version
       tmp.Write<WORD>(0xFFFF); // extended dialog template
       tmp.Write<DWORD>(0); // help ID
       tmp.Write<DWORD>(0); // extended style
       tmp.Write<DWORD>(WS_CAPTION | WS_SYSMENU | DS_SETFONT | DS_MODALFRAME);
       tmp.Write<WORD>(2); // number of controls
       tmp.Write<WORD>(32); // X
       tmp.Write<WORD>(32); // Y
       tmp.Write<WORD>(200); // width
       tmp.Write<WORD>(80); // height
       tmp.WriteString(L""); // no menu
       tmp.WriteString(L""); // default dialog class
       tmp.WriteString(pszTitle); // title
    
       // Next comes the font description.
       // See text for discussion of fancy formula.
       if (ncm.lfMessageFont.lfHeight < 0) {
         ncm.lfMessageFont.lfHeight = -MulDiv(ncm.lfMessageFont.lfHeight,
                  72, GetDeviceCaps(hdc, LOGPIXELSY));
       }
       tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfHeight); // point
       tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfWeight); // weight
       tmp.Write<BYTE>(ncm.lfMessageFont.lfItalic); // Italic
       tmp.Write<BYTE>(ncm.lfMessageFont.lfCharSet); // CharSet
       tmp.WriteString(ncm.lfMessageFont.lfFaceName);
    
       // Then come the two controls.  First is the static text.
       tmp.AlignToDword();
       tmp.Write<DWORD>(0); // help id
       tmp.Write<DWORD>(0); // window extended style
       tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE); // style
       tmp.Write<WORD>(7); // x
       tmp.Write<WORD>(7); // y
       tmp.Write<WORD>(200-14); // width
       tmp.Write<WORD>(80-7-14-7); // height
       tmp.Write<DWORD>(-1); // control ID
       tmp.Write<DWORD>(0x0082FFFF); // static
       tmp.WriteString(pszMessage); // text
       tmp.Write<WORD>(0); // no extra data
    
       // Second control is the OK button.
       tmp.AlignToDword();
       tmp.Write<DWORD>(0); // help id
       tmp.Write<DWORD>(0); // window extended style
       tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE |
                        WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON); // style
       tmp.Write<WORD>(75); // x
       tmp.Write<WORD>(80-7-14); // y
       tmp.Write<WORD>(50); // width
       tmp.Write<WORD>(14); // height
       tmp.Write<DWORD>(IDCANCEL); // control ID
       tmp.Write<DWORD>(0x0080FFFF); // static
       tmp.WriteString(L"OK"); // text
       tmp.Write<WORD>(0); // no extra data
    
       // Template is ready - go display it.
       fSuccess = DialogBoxIndirect(g_hinst, tmp.Template(),
                                    hwnd, DlgProc) >= 0;
      }
      ReleaseDC(NULL, hdc); // fixed 11 May
     }
     return fSuccess;
    }