/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Additional permissions under GNU GPL version 3 section 7 If you modify this Program, or any covered work, by linking or combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK (or a modified version of those libraries), containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the licensors of this Program grant you additional permission to convey the resulting work. Corresponding Source for a non-source form of such a combination shall include the source code for the parts of OpenSSL and IJG JPEG Library used as well as that of the covered work. You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #ifndef plWindow_h_inc #define plWindow_h_inc class plControl; #include class plWindow : public plClass // plClass _must_ be the first base class in list. , public plConfigValueBase { public: HWND fhWnd; WORD fControlID; WORD fTopControlID; bool fDestroyed; bool fMdiChild; plWindow * fOwnerWindow; std::vector fControls; HWND & Handle() { return fhWnd;} const HWND & Handle() const { return fhWnd;} bool fEdited; static int _ModalCount; static std::vector _Windows; static std::vector _DeleteWindows; static LONG APIENTRY StaticWndProc(HWND hWnd, unsigned int message, unsigned int wParam, LONG lParam ) { // look for this hwnd in window list int i; for(i=0; i<_Windows.size(); i++ ) if( _Windows[i]->Handle()==hWnd ) break; if (i==_Windows.size()) { // hsStatusMessage("hwnd not found in _Windows.\n"); } // if window not found and this is WM_NCCREATE or WM_INITDIALOG msg... if( i==_Windows.size() && (message==WM_NCCREATE || message==WM_INITDIALOG || message==WM_ACTIVATE) ) { // get the plWindow object plWindow * WindowCreate = message!=WM_NCCREATE ? (plWindow*)lParam : (GetWindowLong(hWnd,GWL_EXSTYLE) & WS_EX_MDICHILD) ? (plWindow*)((MDICREATESTRUCT*)((CREATESTRUCT*)lParam)->lpCreateParams)->lParam : (plWindow*)((CREATESTRUCT*)lParam)->lpCreateParams; CHECK(WindowCreate); CHECK(!WindowCreate->Handle()); // set the hwnd for this plWindow WindowCreate->Handle() = hWnd; // look for this plWindow in window list for( i=0; i<_Windows.size(); i++ ) if( _Windows[i]==WindowCreate ) break; if (i==_Windows.size()) { hsStatusMessage("plWindow not found in _Windows.\n"); } CHECK(i<_Windows.size()); } // if window not found and message is not WM_NCCREATE or WM_INITDIALOG msg... if( i==_Windows.size() ) { // Gets through before WM_NCCREATE: WM_GETMINMAXINFO return DefWindowProc( hWnd, message, wParam, lParam ); } else { // call the plWindow class's message handler return _Windows[i]->WndProc( message, wParam, lParam ); } } static WNDPROC RegisterWindowClass( const wchar_t * name, DWORD style, int iconId=0 ) { #ifdef UNICODE WNDCLASSEX cls; HSMemory::ClearMemory( &cls, sizeof(cls) ); cls.cbSize = sizeof(cls); cls.style = style; cls.lpfnWndProc = StaticWndProc; cls.hInstance = plWndCtrls::Instance(); cls.hIcon = LoadIcon(plWndCtrls::Instance(),MAKEINTRESOURCE(iconId)); cls.lpszClassName = name; cls.hIconSm = LoadIcon(plWndCtrls::Instance(),MAKEINTRESOURCE(iconId)); CHECK(RegisterClassEx( &cls )); #else char *cName = hsWStringToString(name); WNDCLASSEX cls; HSMemory::ClearMemory( &cls, sizeof(cls) ); cls.cbSize = sizeof(cls); cls.style = style; cls.lpfnWndProc = StaticWndProc; cls.hInstance = plWndCtrls::Instance(); cls.hIcon = LoadIcon(plWndCtrls::Instance(),MAKEINTRESOURCE(iconId)); cls.lpszClassName = cName; cls.hIconSm = LoadIcon(plWndCtrls::Instance(),MAKEINTRESOURCE(iconId)); CHECK(RegisterClassEx( &cls )); delete [] cName; #endif return nil; } plWindow( plWindow * ownerWindow=nil ) : fhWnd (nil) , fControlID (0) , fTopControlID (FIRST_AUTO_CONTROL) , fDestroyed (0) , fMdiChild (0) , fOwnerWindow (ownerWindow) , fEdited (false) { fReadEvaluate = plEvaluate(this,(TEvaluate)HasConfigName); fWriteEvaluate = plEvaluate(this,(TEvaluate)HasConfigName); } virtual ~plWindow() { MaybeDestroy(); std::vector::iterator it = std::find(_DeleteWindows.begin(),_DeleteWindows.end(),this); if (it!=_DeleteWindows.end()) _DeleteWindows.erase(it); } plRect GetClientRect() const { RECT R; ::GetClientRect( Handle(), &R ); return plRect( R ); } plRect GetUpdateRect(bool erase) const { RECT R; ::GetUpdateRect(*this,&R,erase); return plRect(R); } void MoveWindow( plRect R, bool bRepaint ) { ::MoveWindow( Handle(), R.Min.X, R.Min.Y, R.Width(), R.Height(), bRepaint ); } plRect GetWindowRect() const { RECT R; ::GetWindowRect( Handle(), &R ); return fOwnerWindow ? fOwnerWindow->ScreenToClient(R) : plRect(R); } plPoint ClientToScreen( const plPoint& inP ) { POINT P; P.x = inP.X; P.y = inP.Y; ::ClientToScreen( Handle(), &P ); return plPoint( P.x, P.y ); } plPoint ScreenToClient( const plPoint& inP ) { POINT P; P.x = inP.X; P.y = inP.Y; ::ScreenToClient( Handle(), &P ); return plPoint( P.x, P.y ); } plRect ClientToScreen( const plRect& inR ) { return plRect( ClientToScreen(inR.Min), ClientToScreen(inR.Max) ); } plRect ScreenToClient( const plRect& inR ) { return plRect( ScreenToClient(inR.Min), ScreenToClient(inR.Max) ); } plPoint GetCursorPos() { plPoint mouse; ::GetCursorPos( mouse ); return ScreenToClient( mouse ); } void Show( bool show = true ) { ShowWindow( Handle(), show ? SW_SHOW : SW_HIDE ); } void ShowHow( int how ) { ShowWindow( Handle(), how ); } void Hide() { Show(false); } bool IsVisible() { return ::IsWindowVisible(*this)?true:false; } virtual void DoDestroy() { if( Handle() ) DestroyWindow( *this ); std::vector::iterator it = std::find(_Windows.begin(),_Windows.end(),this); if (it!=_Windows.end()) _Windows.erase(it); } virtual void GetWindowClassName( wchar_t * result )=0; virtual LONG WndProc( unsigned int message, unsigned int wParam, LONG lParam ) { try { if( message==WM_DESTROY ) { OnDestroy(); } else if( message==WM_DRAWITEM ) { DRAWITEMSTRUCT * Info = (DRAWITEMSTRUCT*)lParam; for( int i=0; iHandle()==Info->hwndItem ) {((plWindow*)fControls[i])->OnDrawItem(Info); break;} return 1; } else if( message==WM_MEASUREITEM ) { MEASUREITEMSTRUCT * Info = (MEASUREITEMSTRUCT*)lParam; for( int i=0; ifControlID==Info->CtlID ) {((plWindow*)fControls[i])->OnMeasureItem(Info); break;} return 1; } else if ( message==WM_NOTIFY ) { OnNotify((int)wParam,(LPNMHDR)lParam); } else if( message==WM_CLOSE ) { OnClose(); } else if( message==WM_CHAR ) { if (!OnChar( wParam )) // give the control a chance to filter input return FALSE; } else if( message==WM_KEYDOWN ) { OnKeyDown( wParam ); } else if( message==WM_KEYUP ) { OnKeyUp( wParam ); } else if( message==WM_PAINT ) { OnPaint(); } else if( message==WM_CREATE ) { OnCreate(); } else if( message==WM_TIMER ) { OnTimer( (int)wParam ); } else if( message==WM_INITDIALOG ) { OnInitDialog(); } else if( message==WM_SETFOCUS ) { OnSetFocus( (HWND)wParam ); } else if( message==WM_ACTIVATE ) { OnActivate( LOWORD(wParam)!=0 ); } else if( message==WM_KILLFOCUS ) { OnKillFocus( (HWND)wParam ); } else if( message==WM_SIZE ) { OnSize( wParam, LOWORD(lParam), HIWORD(lParam) ); } else if( message==WM_PASTE ) { OnPaste(); } else if( message==WM_SHOWWINDOW ) { OnShowWindow( wParam?true:false ); } else if( message==WM_COPYDATA ) { OnCopyData( (HWND)wParam, (COPYDATASTRUCT*)lParam ); } else if( message==WM_CAPTURECHANGED ) { OnReleaseCapture(); } else if( message==WM_MDIACTIVATE ) { OnMdiActivate( (HWND)lParam==Handle()); } else if( message==WM_MOUSEMOVE ) { OnMouseMove( wParam, plPoint(LOWORD(lParam), HIWORD(lParam)) ); } else if( message==WM_LBUTTONDOWN ) { OnLeftButtonDown(); } else if( message==WM_RBUTTONDOWN ) { OnRightButtonDown(); } else if( message==WM_LBUTTONUP ) { OnLeftButtonUp(); } else if( message==WM_RBUTTONUP ) { OnRightButtonUp(); } else if( message==WM_CUT ) { OnCut(); } else if( message==WM_COPY ) { OnCopy(); } else if( message==WM_UNDO ) { OnUndo(); } else if( message==WM_SETCURSOR ) { if( OnSetCursor() ) return 1; } else if( message==WM_COMMAND || message==WM_HSCROLL || message==WM_VSCROLL ) { for( int i=0; iHandle() && ((plWindow*)fControls[i])->InterceptControlCommand(message,wParam,lParam) ) return 1; OnCommand( wParam ); } else if ( message==WM_SYSCOMMAND ) { OnSysCommand( wParam ); } return CallDefaultProc( message, wParam, lParam ); } catch( const char * e ) { hsStatusMessage( e ); hsStatusMessage("\n"); return 0; } } virtual int CallDefaultProc( unsigned int message, unsigned int wParam, LONG lParam ) { if( fMdiChild ) return DefMDIChildProc( Handle(), message, wParam, lParam ); else return DefWindowProc( Handle(), message, wParam, lParam ); } virtual bool InterceptControlCommand( unsigned int message, unsigned int wParam, LONG lParam ) { return 0; } virtual std::wstring GetText() const { CHECK(Handle()); int length = GetLength(); std::wstring result; if (length==0) return result; result.resize(length); SendMessage( *this, WM_GETTEXT, length+1, (LPARAM)result.data() ); return result; } virtual void SetText( const wchar_t * text ) { CHECK(Handle()); SendMessage( *this, WM_SETTEXT, 0, (LPARAM)text ); } virtual void SetTextF( const wchar_t * fmt, ... ) { va_list args; va_start( args, fmt ); SetTextV( fmt, args ); va_end( args ); } virtual void SetTextV( const wchar_t * fmt, va_list args ) { std::wstring s; xtl::formatv( s, fmt, args ); SetText( s.c_str() ); } virtual void SetEnabled(bool enabled) { CHECK(Handle()); EnableWindow(*this,enabled); } virtual bool IsEnabled() { return IsWindowEnabled(*this)?true:false; } virtual int GetLength() const { CHECK(Handle()); return SendMessage( *this, WM_GETTEXTLENGTH, 0, 0 ); } virtual void SetFocus() { ::SetFocus(*this); } virtual void Activate() { ::SetActiveWindow(*this); } // plWindow notifications. virtual void OnNotify( int idCtrl, LPNMHDR pnmh ) {} virtual void OnCopyData( HWND hWndSender, COPYDATASTRUCT * CD ) {} virtual void OnSetFocus( HWND hWndLosingFocus ) {} virtual void OnKillFocus( HWND hWndGainingFocus ) {} virtual void OnSize( DWORD flags, int newX, int newY ) {} virtual void OnCommand( int command ) {} virtual void OnSysCommand( int command ) {} virtual void OnActivate( bool active ) {} virtual LONG OnChar( char ch ) // Return TRUE if you want to let the default handler grab it, FALSE if you don't {return TRUE;} virtual void OnKeyDown( UInt16 ch ) {} virtual void OnKeyUp( UInt16 ch ) {} virtual void OnCut() {} virtual void OnCopy() {} virtual void OnPaste() {} virtual void OnShowWindow( bool bShow ) {} virtual void OnUndo() {} virtual void OnPaint() {} virtual void OnCreate() {} virtual void OnDrawItem( DRAWITEMSTRUCT * info ) {} virtual void OnMeasureItem( MEASUREITEMSTRUCT * info ) {} virtual void OnInitDialog() {} virtual void OnMouseEnter() {} virtual void OnMouseLeave() {} virtual void OnMouseHover() {} virtual void OnTimer( int timer ) {} virtual void OnReleaseCapture() {} virtual void OnMdiActivate( bool active ) {} virtual void OnMouseMove( DWORD flags, plPoint location ) {} virtual void OnLeftButtonDown() {} virtual void OnRightButtonDown() {} virtual void OnLeftButtonUp() {} virtual void OnRightButtonUp() {} virtual int OnSetCursor() { return 0; } virtual void OnClose() { DestroyWindow( *this ); } virtual void OnDestroy() { CHECK(Handle()); std::vector::iterator it = std::find(_Windows.begin(),_Windows.end(),this); if (it!=_Windows.end()) _Windows.erase(it); Handle() = nil; } // plWindow functions. void MaybeDestroy() { if( !fDestroyed ) { fDestroyed=1; DoDestroy(); } } void _CloseWindow() { CHECK(Handle()); DestroyWindow( *this ); } operator HWND() const { return Handle(); } void SetFont( HFONT hFont ) { SendMessage( *this, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(0,0) ); } void SetSmallIcon( HICON hIcon ) { SendMessage( *this, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); } void SetBigIcon( HICON hIcon ) { SendMessage( *this, WM_SETICON, ICON_BIG, (LPARAM)hIcon); } void PerformCreateWindowEx( DWORD dwExStyle, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance) { CHECK(Handle()==nil); _Windows.push_back( this ); wchar_t className[256]; GetWindowClassName( className ); #ifdef UNICODE HWND hWndCreated = CreateWindowEx( dwExStyle, className, lpWindowName, dwStyle,x,y, nWidth,nHeight, hWndParent,hMenu, plWndCtrls::Instance(), this); #else char *cClassName = hsWStringToString(className); HWND hWndCreated = CreateWindowEx( dwExStyle, cClassName, lpWindowName, dwStyle,x,y, nWidth,nHeight, hWndParent,hMenu, plWndCtrls::Instance(), this); delete [] cClassName; #endif /* #define SAFE(s) ((s)?s:"null") std::strstream str; str << "vars: " << std::endl << dwExStyle << std::endl << SAFE(className) << std::endl << SAFE(lpWindowName) << std::endl << dwStyle << std::endl << x << std::endl << y << std::endl << nWidth << std::endl << nHeight << std::endl << hWndParent << std::endl << hMenu << std::endl << plWndCtrls::Instance() << std::endl << '\0'; MessageBox(nil,str.str(),"",MB_OK); str.freeze(false); */ if( !hWndCreated ) hsStatusMessage( "CreateWindowEx failed" ); CHECK(hWndCreated); CHECK(hWndCreated==Handle()); } void SetRedraw( bool redraw ) { SendMessage( *this, WM_SETREDRAW, redraw, 0 ); } // plConfigValueBase std::string IGetValue() const { std::string sText = ""; char *temp = hsWStringToString(GetText().c_str()); sText = temp; delete [] temp; return sText; } void ISetValue(const char * value) { wchar_t *wValue = hsStringToWString(value); SetText(wValue); delete [] wValue; } virtual void SetEdited(bool value) { fEdited = value; } virtual bool Edited() const { return fEdited; } }; #endif plWindow_h_inc