1 //////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // Nestopia - NES/Famicom emulator written in C++ 4 // 5 // Copyright (C) 2003-2008 Martin Freij 6 // 7 // This file is part of Nestopia. 8 // 9 // Nestopia is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU General Public License as published by 11 // the Free Software Foundation; either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Nestopia is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Nestopia; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 //////////////////////////////////////////////////////////////////////////////////////// 24 25 #include "language/resource.h" 26 #include "NstApplicationException.hpp" 27 #include "NstWindowCustom.hpp" 28 #include "NstWindowParam.hpp" 29 #include "NstWindowStatusBar.hpp" 30 #include <CommCtrl.h> 31 32 namespace Nestopia 33 { 34 namespace Window 35 { Width(const uint n)36 inline StatusBar::Width::Width(const uint n) 37 : numChars(n) {} 38 Calculate(HWND const hWnd)39 void StatusBar::Width::Calculate(HWND const hWnd) 40 { 41 NST_ASSERT( hWnd ); 42 43 character = DEF_CHAR_WIDTH; 44 first = DEF_FIRST_WIDTH; 45 46 if (HDC const hDC = ::GetDC( hWnd )) 47 { 48 TEXTMETRIC tm; 49 50 if (::GetTextMetrics( hDC, &tm )) 51 character = tm.tmAveCharWidth; 52 53 first = character * numChars; 54 55 ::ReleaseDC( hWnd, hDC ); 56 } 57 } 58 StatusBar(Custom & p,const uint numChars)59 StatusBar::StatusBar(Custom& p,const uint numChars) 60 : 61 width ( numChars ), 62 parent ( p ) 63 { 64 static const MsgHandler::HookEntry<StatusBar> hooks[] = 65 { 66 { WM_SIZE, &StatusBar::OnSize }, 67 { WM_DESTROY, &StatusBar::OnDestroy } 68 }; 69 70 parent.Messages().Hooks().Add( this, hooks ); 71 } 72 ~StatusBar()73 StatusBar::~StatusBar() 74 { 75 window.Destroy(); 76 parent.Messages().Hooks().Remove( this ); 77 } 78 Enable(const bool enable,const bool show)79 void StatusBar::Enable(const bool enable,const bool show) 80 { 81 NST_ASSERT( bool(parent) ); 82 83 if (enable) 84 { 85 if (window == NULL) 86 { 87 window = CreateWindowEx 88 ( 89 0, 90 STATUSCLASSNAME, 91 NULL, 92 WS_CHILD|SBARS_SIZEGRIP|(show ? WS_VISIBLE : 0), 93 0,0,0,0, 94 parent, 95 reinterpret_cast<HMENU>(CHILD_ID), 96 ::GetModuleHandle(NULL), 97 NULL 98 ); 99 100 if (window == NULL) 101 throw Application::Exception( IDS_ERR_FAILED, L"CreateWindowEx()" ); 102 103 width.Calculate( window ); 104 Update(); 105 } 106 } 107 else 108 { 109 window.Destroy(); 110 } 111 } 112 OnDestroy(Param &)113 void StatusBar::OnDestroy(Param&) 114 { 115 window.Destroy(); 116 } 117 Show() const118 void StatusBar::Show() const 119 { 120 window.Show(); 121 } 122 operator <<(wcstring text) const123 void StatusBar::Stream::operator << (wcstring text) const 124 { 125 if (window) 126 window.Send( SB_SETTEXT, field|0, text ); 127 } 128 Clear() const129 void StatusBar::Stream::Clear() const 130 { 131 operator << (L""); 132 } 133 GetMaxMessageLength() const134 uint StatusBar::GetMaxMessageLength() const 135 { 136 if (window) 137 { 138 int list[2] = {0,0}; 139 window.Send( SB_GETPARTS, 2, list ); 140 141 if (list[0] > int(width.character)) 142 return uint(list[0]) / (width.character - 1); 143 } 144 145 return 0; 146 } 147 Update() const148 void StatusBar::Update() const 149 { 150 NST_ASSERT( window && parent ); 151 152 int list[2] = { parent.ClientCoordinates().x - int(width.first), -1 }; 153 window.Send( SB_SETPARTS, 2, list ); 154 } 155 OnSize(Param & param)156 void StatusBar::OnSize(Param& param) 157 { 158 if (window) 159 { 160 window.Send( WM_SIZE, param.wParam, param.lParam ); 161 Update(); 162 } 163 } 164 Height() const165 uint StatusBar::Height() const 166 { 167 if (window) 168 { 169 const int height = window.Coordinates().Height(); 170 171 if (height > 0) 172 return height; 173 } 174 175 return 0; 176 } 177 } 178 } 179 180