core/vgui/impl/win32/vgui_win32_window.cxx
Go to the documentation of this file.
00001 // This is core/vgui/impl/win32/vgui_win32_window.cxx
00002 
00003 #include "vgui_win32_window.h"
00004 #include "vgui_win32_utils.h"
00005 #include <vgui/vgui.h>
00006 #include <vgui/vgui_command.h>
00007 
00008 BEGIN_MESSAGE_MAP(vgui_win32_window, vgui_win32_cmdtarget)
00009 END_MESSAGE_MAP()
00010 
00011 LRESULT vgui_win32_window::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
00012 {
00013   if ( OnCmdMsg(message, wParam, lParam) )
00014     return 1;
00015   else
00016     return DefWndProc(hwnd, message, wParam, lParam);
00017 }
00018 
00019 LRESULT vgui_win32_window::DefWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
00020 {
00021   // Note: must NOT call DefWindowProc(hwnd, message, wParam, lParam);
00022   return 0;
00023 }
00024 
00025 vgui_win32_window::vgui_win32_window(HINSTANCE hInst, const char *appName,
00026                                      int width, int height, vgui_menu const &menubar, char const *title)
00027 : cx_(width), cy_(height), first_show(true)
00028 {
00029   initWindow(hInst, appName, width, height, title);
00030 
00031   // Convert vgui_menu to Win32 menu handle (HMENU) to add it to the main window.
00032   hMenu_ = vgui_win32_utils::instance()->vgui_menu_to_win32ex(menubar, callbacks, &hAccel_);
00033   SetMenu(hwnd_, hMenu_);
00034 }
00035 
00036 vgui_win32_window::vgui_win32_window(HINSTANCE hInst, const char *appName,
00037                                      int width, int height, char const *title)
00038 : cx_(width), cy_(height), first_show(true)
00039 {
00040   initWindow(hInst, appName, width, height, title);
00041 }
00042 
00043 void vgui_win32_window::initWindow(HINSTANCE hInst, const char *appName,
00044                                    int width, int height, char const *title)
00045 {
00046   hMenu_ = NULL;
00047   hAccel_ = NULL;
00048 
00049   // In VGUI applications, the window size (width, height) passed from
00050   // vgui::produce_window is usually the image size. Whereas the width
00051   // and height arguments in function CreateWindow is the window size
00052   // including UIs like title bar, menu bar, status bar and window frame.
00053   // Therefore it's better to take account of the dimension of these
00054   // UIs so that the entire image can be shown.
00055 
00056   // Get the size of UIs
00057   int cxSizeFrame  = GetSystemMetrics(SM_CXSIZEFRAME);
00058   int cySizeFrame  = GetSystemMetrics(SM_CYSIZEFRAME);
00059   int cyCaption    = GetSystemMetrics(SM_CYCAPTION);
00060   int cyMenu       = GetSystemMetrics(SM_CYMENU);
00061   int cxScreenSize = GetSystemMetrics(SM_CXFULLSCREEN);
00062   int cyScreenSize = GetSystemMetrics(SM_CYFULLSCREEN);
00063   int cxVScroll    = GetSystemMetrics(SM_CXVSCROLL);
00064   int cyHScroll    = GetSystemMetrics(SM_CYHSCROLL);
00065 
00066   // Compute a reasonable vgui app window size
00067   int win_width = width+2*cxSizeFrame+3; //+cxVScroll;
00068   int win_height = height+cyCaption+cyMenu+2*cySizeFrame; //+cyHScroll;
00069 
00070   // But consider the case that image size is larger than the screen size
00071   if ( win_width > cxScreenSize ) {
00072     win_width = cxScreenSize;
00073     cx_ = cxScreenSize-(2*cxSizeFrame);
00074   }
00075   if ( win_height > cyScreenSize ) {
00076     win_height = cyScreenSize;
00077     cy_ = cyScreenSize-(cyCaption+cyMenu+2*cySizeFrame);
00078   }
00079 
00080   hwnd_ = CreateWindow(appName,             // window class name
00081                        title,               // window caption
00082                        WS_OVERLAPPEDWINDOW, // window style
00083                        CW_USEDEFAULT,       // initial x position
00084                        CW_USEDEFAULT,       // initial y position
00085                        win_width,           // window width
00086                        win_height,          // window height
00087                        NULL,                // parent window handle
00088                        NULL,                // window menu handle
00089                        hInst,               // program instance handle
00090                        NULL                 // creation parameters
00091                       );
00092   adaptor_ = new vgui_win32_adaptor(hwnd_, this);
00093   statusbar_ = new vgui_win32_statusbar(hwnd_);
00094   vgui::out.rdbuf(statusbar_->statusbuf); // redirect to status bar.
00095 
00096   // These two lines may be duplicated as vgui_window::show() has already
00097   // been called in vgui::adapt(), which is called by vgui::run().
00098   ShowWindow(hwnd_, SW_SHOWNORMAL);
00099   UpdateWindow(hwnd_);
00100 }
00101 
00102 vgui_win32_window::~vgui_win32_window()
00103 {
00104   delete statusbar_;
00105   statusbar_ = 0;
00106 
00107   DestroyMenu(hMenu_);
00108   hMenu_ = NULL;
00109   callbacks.clear();
00110 
00111   DestroyAcceleratorTable(hAccel_);
00112 }
00113 
00114 // Display the window.
00115 void vgui_win32_window::show()
00116 {
00117   ShowWindow(hwnd_, SW_SHOW);
00118   UpdateWindow(hwnd_);
00119 
00120   // These two message are posted so that the embedded adaptor can
00121   // obtain its size at the application startup.
00122   // The reason to do so is that the WM_SIZE message and the WM_PAINT
00123   // message sent at application initialization stage cannot be reached to
00124   // either vgui_win32_window or vgui_win32_adaptor, which is unborn then.
00125   // Other ways for the adaptor to get these messages at startup is welcomed.
00126   if ( first_show ) {
00127     PostMessage(hwnd_, WM_SIZE, 0, MAKELPARAM((WORD)(cx_+3),(WORD)(cy_) ));
00128     PostMessage(hwnd_, WM_PAINT, 0, 0);
00129     first_show = false;
00130   }
00131 }
00132 
00133 // TODO: This function is not called yet.
00134 // Change window shape to new given width and height.
00135 void vgui_win32_window::reshape(unsigned w, unsigned h)
00136 {
00137    cx_ = w; cy_ = h;
00138    MoveWindow(hwnd_, wx_, wy_, cx_, cy_, TRUE);
00139 }
00140 
00141 // TODO: This function is not called yet.
00142 // Move the window to the new given x,y position.
00143 void vgui_win32_window::reposition(int x, int y)
00144 {
00145   wx_ = x; wy_ = y;
00146   MoveWindow(hwnd_, wx_, wy_, cx_, cy_, TRUE);
00147 }
00148 
00149 
00150 // Put the given menu in the menubar (if it exists).
00151 void vgui_win32_window::set_menubar(vgui_menu const &menu)
00152 {
00153   // Remove the existent menu handle if it exists.
00154   if ( hMenu_ ) {
00155     DestroyMenu(hMenu_);
00156     hMenu_ = NULL;
00157   }
00158   callbacks.clear();
00159 
00160   // Convert vgui_menu to Win32 MENUTEMPLATE to load the new menu.
00161   hMenu_ = vgui_win32_utils::instance()->vgui_menu_to_win32ex(menu, callbacks, &hAccel_);
00162   SetMenu(hwnd_, hMenu_);
00163   // The changed menu won't be updated unless it is forced to be redrawn.
00164   DrawMenuBar(hwnd_);
00165 }
00166 
00167 
00168 // If true, activate the statusbar (if it exists).
00169 void vgui_win32_window::set_statusbar(bool on)
00170 {
00171   if ( statusbar_ )
00172     statusbar_->setVisible(on);
00173 }
00174 
00175 
00176 // If true, activate horizontal scrollbar (if it exists).
00177 void vgui_win32_window::enable_hscrollbar(bool b)
00178 {
00179   EnableScrollBar(hwnd_, SB_HORZ, b ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
00180   ShowScrollBar(hwnd_, SB_HORZ, b);
00181 }
00182 
00183 
00184 // If true, activate vertical scrollbar (if it exists).
00185 void vgui_win32_window::enable_vscrollbar(bool b)
00186 {
00187   EnableScrollBar(hwnd_, SB_VERT, b ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
00188   ShowScrollBar(hwnd_, SB_VERT, b);
00189 }
00190 
00191 // Set the position of the horizontal scrollbar, returns old position
00192 int vgui_win32_window::set_hscrollbar(int pos)
00193 {
00194   SCROLLINFO si;
00195   int oldPos;
00196 
00197   si.cbSize = sizeof(si);
00198   si.fMask = SIF_POS;
00199 
00200   GetScrollInfo(hwnd_, SB_HORZ, &si);
00201   oldPos = si.nPos;
00202 
00203   si.nPos = pos;
00204   SetScrollInfo(hwnd_, SB_HORZ, &si, TRUE);
00205 
00206   return oldPos;
00207 }
00208 
00209 // Set the position of the vertical scrollbar, returns old position
00210 int vgui_win32_window::set_vscrollbar(int pos)
00211 {
00212   SCROLLINFO si;
00213   int oldPos;
00214 
00215   si.cbSize = sizeof(si);
00216   si.fMask = SIF_POS;
00217 
00218   GetScrollInfo(hwnd_, SB_VERT, &si);
00219   oldPos = si.nPos;
00220 
00221   si.nPos = pos;
00222   SetScrollInfo(hwnd_, SB_VERT, &si, TRUE);
00223 
00224   return oldPos;
00225 }
00226 
00227 void vgui_win32_window::menu_dispatcher(int menuId)
00228 {
00229   int item_count = callbacks.size();
00230 
00231   // Make sure nID is in the relevant range, and
00232   // call the callback function associated with the menu item "menuId"
00233   if ( menuId >= MENU_ID_START && menuId < MENU_ID_START+item_count )
00234     callbacks[menuId-MENU_ID_START]->execute();
00235 }
00236 
00237 // Handle messages that are related to vgui_window.
00238 BOOL vgui_win32_window::OnCmdMsg(UINT message, WPARAM wParam, LPARAM lParam)
00239 {
00240   if ( adaptor_ )
00241     adaptor_->OnCmdMsg(message, wParam, lParam);
00242 
00243   switch (message) {
00244     case WM_SIZE:
00245       cx_ = LOWORD(lParam);
00246       cy_ = HIWORD(lParam);
00247       // redraw status bar
00248       SendMessage(statusbar_->getWindowHandle(), WM_SIZE, wParam, lParam);
00249       break;
00250 
00251     case WM_COMMAND: // child window and menu message
00252       menu_dispatcher(LOWORD(wParam));
00253       return TRUE;
00254 
00255     case WM_CLOSE:
00256       delete adaptor_;
00257       adaptor_ = 0;
00258       break;
00259 
00260     //case WM_DESTROY:
00261     //  PostQuitMessage(0);
00262     //  break;
00263   }
00264 
00265   return FALSE;
00266 }
00267