如何在使用C++编程时,在win32中创建一个子窗口?

4

我对C++和Windows编程都很陌生。

我使用MSDN的CreateWindow()函数创建了一个窗口,它可以正常工作。

现在,我想创建一个子窗口,父窗口应该控制子窗口。

请提供任何有关此问题的示例代码。

谢谢您提前的帮助。

4个回答

7
粗略地说,在父处理程序中,您希望创建子窗口的位置,调用CreateWindow,将父窗口作为hwndParent传递-可能还要在子窗口上设置某些样式,如WS_CHILD。然后,您与子窗口的交互取决于您创建的窗口类型。一些窗口(例如按钮)被设计为工作作为子窗口,因此它们发送许多通知消息,因此您需要设置父级以侦听这些通知消息。

6
我强烈建议您阅读Charles Petzold的《Windows编程》(如果您可以获得一本副本)。
否则,为了回答您的问题,在创建子窗口时将父窗口的句柄作为父窗口传递(使用CreateWindow或CreateWindowEx)。
HWND CreateWindowEx
(      
    DWORD dwExStyle,
    LPCTSTR lpClassName,
    LPCTSTR lpWindowName,
    DWORD dwStyle,
    int x,
    int y,
    int nWidth,
    int nHeight,
    HWND hWndParent,      /// pass the parent window handle here
    HMENU hMenu,
    HINSTANCE hInstance,
    LPVOID lpParam
);

如1800 Info所述,也许还需要设置WS_CHILD样式(更多关于窗口样式的信息)。这只是基本的管道工作。

当您说“控制子窗口”时,能否具体说明一下?


6
现在是2018年。我正在进行一些复古工作,发现使用SetParent()很方便,可以确保子窗口保持在父窗口的客户区内。在使用SetParent()之前,子窗口不需要被注册为子级。在CreateWindowEx中,父句柄起初可以为NULL。样式WS_CHILD并不需要,但WS_CLIPSIBLINGS非常有用,它避免了闪烁。
以下是我创建子窗口的代码:
    HWND hwnd = CreateWindowExA(0, "WindowOfDLL", ctitle, WS_SIZEBOX | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, hMenu, inj_hModule, NULL);
    SetParent(hwnd, hwndparent);
    ShowWindow(hwnd, SW_SHOWNORMAL);

我在Win10中尚未看到线程方面的问题。下面的每个子窗口都是在管理程序集的DLL中创建的。当创建子窗口时,DLL会向程序集添加一个新成员并启动一个线程,该线程将为子窗口提供服务并在其初始化时执行上述代码。

parent window with WS_CLIPCHILDREN


所以我在考虑发布自己的问题,涉及到如何让一个子窗口工作,因为我一直没有成功地加载它。我使用了你的代码,并进行了一些更改 - HWND hwnd = CreateWindowExA(0, "WindowOfDLL", "child", WS_SIZEBOX | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, NULL, hInstance, NULL); - 给出了明确的子窗口名称,移除了菜单,并指向了我的hInstance。但我一直无法成功地将其加载。你能否发布更多的代码,以便我可以看看我做错了什么? - Brad B.

0
"could you post more of your code "

@BradB 你说得对,我们的答案都不是很具体,这是老东西,很难在一个帖子中完整地概括。我建议你读一下RobS推荐的书...并且...看一下Visual Studio和更现代的方法来设计“子窗口”,比如Winforms、WPF和Universal!

这里有一些我的遗留代码,只是为了让它成为一个子窗口的准备工作。事件等你需要自己填写...

 BOOL RegisterDLLWindowClass(LPCWSTR s)
    {
      WNDCLASSEX wc;
      wc.hInstance = NULL; // inj_hModule;
      wc.lpszClassName = s;
      wc.lpfnWndProc = DLLWindowProc;
      wc.style = CS_DBLCLKS;
      wc.cbSize = sizeof(WNDCLASSEX);
      wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
      wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
      wc.hCursor = LoadCursor(NULL, IDC_ARROW);
      wc.lpszMenuName = NULL;
      wc.cbClsExtra = 0;
      wc.cbWndExtra = 0;
      wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
      if (!RegisterClassEx(&wc))
        return 0;
    }

    HMENU CreateDLLWindowMenu()
        {
          WriteLine("Create menu");
          HMENU hMenu;
          hMenu = CreateMenu();
          HMENU hMenuPopup;
          if (hMenu == NULL)
            return FALSE;
          hMenuPopup = CreatePopupMenu();
          AppendMenu(hMenuPopup, MF_STRING, MYMENU_FILTERSOFF, TEXT("Off"));
          AppendMenu(hMenuPopup, MF_STRING, MYMENU_CANNY, TEXT("Canny"));
          AppendMenu(hMenuPopup, MF_STRING, MYMENU_SOBEL, TEXT("Sobel"));
          AppendMenu(hMenuPopup, MF_STRING, MYMENU_THRESHOLD, TEXT("Threshold"));
          AppendMenu(hMenuPopup, MF_STRING, MYMENU_DILATE, TEXT("Dilate"));
          AppendMenu(hMenuPopup, MF_STRING, MYMENU_HARRIS, TEXT("Harris"));
          CheckMenuItem(hMenuPopup, 0, MF_BYPOSITION | MF_CHECKED);

          AppendMenuW(hMenu, MF_POPUP, (UINT_PTR)hMenuPopup, TEXT("Filter"));

          HMENU hMenuPopup2 = CreatePopupMenu();
          AppendMenu(hMenuPopup2, MF_STRING, MYMENU_SAMPLE1, TEXT("Change parameter"));
          AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hMenuPopup2, TEXT("Test"));
          return hMenu;
        }

    void WINAPI CreateAWindow(PassedToDLL *lpParam, DWORD dwStyle)
        {   
          if (nInstances == 0) RegisterDLLWindowClass((LPCWSTR)L"WindowOfDLL");
          HMENU hMenu = CreateDLLWindowMenu();
          nInstances++;
          CommonInfo[nInstances - 1] = lpParam;
          int i = 20 + 4 * (rand() % 10);
          lpParam->p = NewPanningStruct();
          lpParam->hWndChild = CreateWindowEx(0, L"WindowOfDLL", lpParam->title,
                dwStyle,
                i, i, 800, 550, lpParam->hWndParent, hMenu, NULL, NULL);
          if (wcslen(lpParam->filename) > 0)
          {
            LoadBitmapFromBMPFileW(lpParam->hWndChild, lpParam->filename, &(lpParam->hBmp),
                &(lpParam->hPalette));
          } 
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接