我可以在没有资源脚本的情况下制作 属性 sheet 吗?

Can I make a property sheet without resource script?

我想在没有资源脚本的情况下向 property sheet 添加控件,而不是使用纯代码。 这样做的原因我想创建一个 属性 sheet(模仿 C# 的 property grid),从另一种语言调用 C routines/WINAPI,与 C 二进制兼容;但我想用代码定义所有内容,而不需要资源脚本。这是可能的还是要走的路是写我自己的 属性-sheet-like,底层 CreateWindow*() 调用? (欢迎使用不同的方法,我是 WINAPI 的新手)我想 属性 sheet 在幕后使用

找到解决方案!我从 Raymond Chen 那里找到了 this post,他展示了如何做到这一点。

主要代码如下:

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;
}