none
如何让 Rebar 自动适应窗口尺寸,即尺寸随窗口的改变而改变? RRS feed

  • 问题

  • 这是一段生成一个含有 Rebar 及 Toolbar 的窗口的 C 代码:

    #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
    #pragma comment(lib, "ComCtl32.Lib")
    
    #include <windows.h>
    #include <commctrl.h>
    
    #define ID_FILE_OPEN 0xe101
    
    HINSTANCE g_h_instance;
    
    LRESULT CALLBACK main_window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpwCmdLine, int nCmdShow)
    {
      WNDCLASSEX wcex;
      LPCWSTR lpcw_class_name = L"Main Window Class";
      HWND hwnd;
      MSG msg;
      BOOL b_ret;
    
      g_h_instance = hInstance;
    
      wcex.cbSize = sizeof(wcex);
      wcex.style = CS_HREDRAW | CS_VREDRAW;
      wcex.lpfnWndProc = main_window_proc;
      wcex.cbClsExtra = 0;
      wcex.cbWndExtra = 0;
      wcex.hInstance = hInstance;
      wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
      wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
      wcex.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
      wcex.lpszMenuName = NULL;
      wcex.lpszClassName = lpcw_class_name;
      wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    
      if (!RegisterClassEx(&wcex))
      {
        return EXIT_FAILURE;
      }
    
      if (!(hwnd = CreateWindowEx(0, lpcw_class_name, L"Test", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_h_instance, NULL)))
      {
        return EXIT_FAILURE;
      }
    
      ShowWindow(hwnd, nCmdShow);
      UpdateWindow(hwnd);
    
      while (b_ret = GetMessage(&msg, NULL, 0, 0))
      {
        if (b_ret == -1)
        {
          return EXIT_FAILURE;
        }
        else
        {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
        }
      }
      return msg.wParam;
    }
    
    LRESULT CALLBACK main_window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
      switch (uMsg)
      {
      case WM_CREATE:
        {
          const int n_btn_num = 1, n_il_id = 0, n_bmp_size = 16;
          HIMAGELIST h_il;
          TBBUTTON tbs[1];
          REBARBANDINFO rbi;
          DWORD dw_btn_size;
          HWND h_rebar, h_toolbar;
    
          if (!(h_rebar = CreateWindowEx(0, REBARCLASSNAME, NULL,
            WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE | CCS_NODIVIDER | RBS_VARHEIGHT,
            0, 0, 0, 0, hWnd, NULL, g_h_instance, NULL)))
          {
            exit(EXIT_FAILURE);
          }
          if (!(h_toolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
            WS_CHILD | WS_VISIBLE | CCS_NODIVIDER |/* CCS_NOPARENTALIGN | CCS_NORESIZE |*/
            TBSTYLE_FLAT | TBSTYLE_LIST | TBSTYLE_TRANSPARENT,
            0, 0, 0, 0, h_rebar, NULL, g_h_instance, NULL)))
          {
            exit(EXIT_FAILURE);
          }
          SendMessage(h_toolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
          h_il = ImageList_Create(n_bmp_size, n_bmp_size, ILC_MASK | ILC_COLOR32, n_btn_num, 0);
          SendMessage(h_toolbar, TB_SETIMAGELIST, (WPARAM)n_il_id, (LPARAM)h_il);
          SendMessage(h_toolbar, TB_LOADIMAGES, (WPARAM)IDB_STD_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
          tbs[0].iBitmap = MAKELONG(STD_FILEOPEN, n_il_id);
          tbs[0].idCommand = ID_FILE_OPEN;
          tbs[0].fsState = TBSTATE_ENABLED;
          tbs[0].fsStyle = BTNS_AUTOSIZE;
          tbs[0].bReserved[0] = 0;
          tbs[0].dwData = 0;
          tbs[0].iString = (INT_PTR)L"Open";
          SendMessage(h_toolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(*tbs), 0);
          SendMessage(h_toolbar, TB_ADDBUTTONS, (WPARAM)n_btn_num, (LPARAM)&tbs);
          dw_btn_size = (DWORD)SendMessage(h_toolbar, TB_GETBUTTONSIZE, 0,0);
          rbi.cbSize = sizeof(rbi);
          rbi.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;
          rbi.fStyle = RBBS_CHILDEDGE | RBBS_VARIABLEHEIGHT;
          rbi.lpText = L"";
          rbi.hwndChild = h_toolbar;
          rbi.cyChild = HIWORD(dw_btn_size);
          rbi.cxMinChild = n_btn_num * LOWORD(dw_btn_size);
          rbi.cyMinChild = HIWORD(dw_btn_size);
          rbi.cx = 0;
          SendMessage(h_rebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
          break;
        }
      case WM_DESTROY:
        PostQuitMessage(EXIT_SUCCESS);
        break;
      default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
      }
      return 0;
    }</commctrl.h></windows.h>

    然而以这种方法创建出的 Rebar 的尺寸是固定的。MSDN 上说“The toolbar default sizing and positioning behaviors can be turned off by setting the CCS_NORESIZE and CCS_NOPARENTALIGN common control styles. Toolbar controls that are hosted by rebar controls must set these styles because the rebar control sizes and positions the toolbar”,但如果我加上 CCS_NORESIZE 和 CCS_NOPARENTALIGN 样式后,Toolbar 的位置就跑到了可视区域之外(这是由 Spy++ 检查出来的)。那么如何才能使 Rebar 占满整一行?


    EFanZh


    • 已编辑 EFanZh 2012年2月13日 17:35
    2012年2月13日 17:31

答案

  • 需要自己处理WM_SIZE消息,调用类似MFC类中的CFrameWnd::RecalcLayout/ CWnd::RepositionBars()


    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.

    • 已建议为答案 Helen Zhao 2012年2月15日 6:08
    • 已标记为答案 EFanZh 2012年2月17日 13:06
    2012年2月14日 3:09
    版主