PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 1/12 TITLE : Customizing the attributes and style of a Window. // // MOD.CPP // Example to demonstrate typical modifications one makes to windows. // #include #include #include #include #include #include #pragma hdrstop #include "modrc.h" class TMyApp : public TApplication { public: TMyApp(LPSTR AName, HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) : TApplication(AName, hInstance, hPrevInstance, lpCmdLine, nCmdShow) {}; virtual void InitMainWindow(); }; _CLASSDEF(TMyWindow) class TMyWindow : public TWindow { public: TMyWindow(PTWindowsObject AParent, LPSTR ATitle) : TWindow(AParent, ATitle) { AssignMenu( "MENU_1"); }; virtual void CMDemoWMCTLColor(RTMessage Msg) = [CM_FIRST + CM_DEMO_WM_CTLCOLOR ]; virtual void CMDemoWMSetFont(RTMessage Msg) = [CM_FIRST + CM_DEMO_WM_SETFONT ]; virtual void CMDemoStyle(RTMessage Msg) = [CM_FIRST + CM_DEMO_STYLE ]; virtual void CMDemoClassChange( RTMessage Msg ) = [ CM_FIRST + CM_CLASS_CHANGE ]; virtual void CMDemoWMSetCursor( RTMessage Msg ) = [ CM_FIRST + CM_DEMO_WM_SETCURSOR ]; PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 2/12 TITLE : Customizing the attributes and style of a Window. virtual void CMDemoBackground( RTMessage Msg ) = [ CM_FIRST + CM_DEMO_BACKGROUND ]; }; _CLASSDEF( TDemoWindow ) // Base class to create the child controls, set the style of the demo // window and manage the initial position of the demo windows. class TDemoWindow : public TWindow { public: TDemoWindow(PTWindowsObject AParent, LPSTR ATitle); virtual void SetupWindow(); PTListBox listbox; PTEdit edit; PTStatic _static; static int delta; }; int TDemoWindow::delta = 0; TDemoWindow::TDemoWindow( PTWindowsObject AParent, LPSTR ATitle ) : TWindow( AParent , ATitle ) { Attr.X = 10 + delta; Attr.Y = 10 + delta; Attr.W = 200 ; Attr.H = 200 ; // delta is used so that the child windows don't all appear in // the same place. delta += 10; if ( delta > 100 ) delta = 0; EnableKBHandler(); Attr.Style = WS_CAPTION | WS_BORDER | WS_POPUP | WS_CLIPSIBLINGS| WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE; edit = new TEdit( this , 101 , "edit control", 10, 10, 100, 25, 0 , FALSE); PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 3/12 TITLE : Customizing the attributes and style of a Window. _static = new TStatic( this , 102 , "static control", 10, 40, 100, 25 , 0 ); listbox = new TListBox( this , 103, 10, 70, 100, 40 ); } void TDemoWindow::SetupWindow() { TWindow::SetupWindow(); listbox->AddString("string 1"); listbox->AddString("string 2" ); } _CLASSDEF( TColorWindow ) // Window which demonstrates using the WM_CTLCOLOR message to control // the color of child controls. The online help for WM_CTLCOLOR // gives a lot of information for using it. An often overlooked // function of this message is that it is also used // to control the color of dialog box backgrounds. class TColorWindow : public TDemoWindow { public: TColorWindow(PTWindowsObject AParent, LPSTR ATitle); ~TColorWindow(); virtual void WMCTLColor(RTMessage Msg) = [WM_FIRST + WM_CTLCOLOR ]; HBRUSH MyBrush; }; TColorWindow::TColorWindow( PTWindowsObject AParent , LPSTR ATitle ) : TDemoWindow(AParent, ATitle) { MyBrush = CreateSolidBrush( RGB( 0, 0xFF, 0xFF) ); }; TColorWindow::~TColorWindow( ) { DeleteObject( MyBrush ); } void TColorWindow::WMCTLColor( RTMessage msg ) { HDC & hdc = (HDC) msg.WParam; PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 4/12 TITLE : Customizing the attributes and style of a Window. HWND hwnd = (HWND)msg.LP.Lo; int nCtl = (int)msg.LP.Hi; if ( nCtl == CTLCOLOR_EDIT ) { // we can modify things about the hdc SetTextColor( hdc , RGB( 0xFF, 0xFF , 0x0 )); // you must return a valid brush! msg.Result = (DWORD)GetStockObject( BLACK_BRUSH ); // to change the background color of a single line edit // control, we must do more (see online help on WM_CTLCOLOR // for details SetBkColor( hdc, RGB( 0, 0, 0 )); } // though there are no messageboxes on the window, the online help // for WM_CTLCOLOR indicates to use the same background brush here // that you do for the edit control. else if ( nCtl == CTLCOLOR_MSGBOX ) { msg.Result = (DWORD)GetStockObject( BLACK_BRUSH ); } else if ( nCtl == CTLCOLOR_STATIC ) { SetTextColor( hdc, RGB( 0x0, 0xFF, 0x0 )); msg.Result = (DWORD)GetStockObject( BLACK_BRUSH ); SetBkColor( hdc, RGB( 0,0,0)); } else if ( hwnd == listbox->HWindow ) { msg.Result = (DWORD) MyBrush; // we probably should use SetBkColor, but this lets the // background brush show behind the text SetBkMode( hdc, TRANSPARENT ); } // pass ones we don't handle on for default processing else DefWndProc( msg ); } void TMyWindow::CMDemoWMCTLColor(RTMessage) PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 5/12 TITLE : Customizing the attributes and style of a Window. { PTColorWindow ColorWindow = new TColorWindow( this , "WM_CTLCOLOR demo window" ); GetApplication()->MakeWindow( ColorWindow ); } _CLASSDEF( TFontWindow ) // window to demo changing the fonts for controls by sending them the // WM_SETFONT message. class TFontWindow : public TDemoWindow { public: TFontWindow(PTWindowsObject AParent, LPSTR ATitle); ~TFontWindow(); virtual void SetupWindow(); HFONT editFont, listFont; }; TFontWindow::TFontWindow(PTWindowsObject AParent, LPSTR ATitle ) : TDemoWindow( AParent , ATitle ) { // get some stock fonts HFONT ansiFixed = (HFONT)GetStockObject( ANSI_FIXED_FONT ); HFONT ansiVar = (HFONT)GetStockObject( ANSI_VAR_FONT ); LOGFONT lfAnsiFixed, lfAnsiVar; // get their description GetObject( ansiFixed , sizeof( lfAnsiFixed), &lfAnsiFixed ); GetObject( ansiVar , sizeof( lfAnsiVar ) , &lfAnsiVar); // tweek them, though if you play with these attributes, you'll // find that not everything works when you finally send the font // to the controls, // however this is a good technique for making your own fonts. lfAnsiFixed.lfWidth += 20; lfAnsiVar.lfWidth += 20; lfAnsiVar.lfHeight -= 5; editFont = CreateFontIndirect( &lfAnsiVar ); listFont = CreateFontIndirect( &lfAnsiFixed ); } PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 6/12 TITLE : Customizing the attributes and style of a Window. void TFontWindow::SetupWindow() { TDemoWindow::SetupWindow(); SendMessage( edit->HWindow , WM_SETFONT , (WPARAM) editFont, 0L ); SendMessage( listbox->HWindow , WM_SETFONT , (WPARAM) listFont, 0L ); } TFontWindow::~TFontWindow() { DeleteObject( editFont ); DeleteObject( listFont ); } void TMyWindow::CMDemoWMSetFont(RTMessage) { PTFontWindow FontWindow = new TFontWindow( this , "WM_SETFONT demo window" ); GetApplication()->MakeWindow( FontWindow ); } _CLASSDEF( TStyleWindow ) // Window which demonstrates changing the style of a window after it // is created. Here, we take away the WS_BORDER style from a // listbox to make it come up without a border. class TStyleWindow : public TDemoWindow { public: TStyleWindow(PTWindowsObject AParent, LPSTR ATitle); virtual void SetupWindow(); }; TStyleWindow::TStyleWindow(PTWindowsObject AParent, LPSTR ATitle ) : TDemoWindow( AParent , ATitle ) { } void TStyleWindow::SetupWindow() { TDemoWindow::SetupWindow(); PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 7/12 TITLE : Customizing the attributes and style of a Window. // since most standard controls will set there styles when // they are created, it does not matter what you do with the // Attr.Style data member. Here, we take away the WS_BORDER // style of the listbox. Incidently, edit controls don't use // a WS_BORDER style, which means they must be painting it // themselves in response to the WM_PAINT message, so the following // technique would not remove there border. DWORD currentStyle = GetWindowLong( listbox->HWindow , GWL_STYLE ); DWORD temp = currentStyle ^ WS_BORDER ; currentStyle &= temp; SetWindowLong( listbox->HWindow , GWL_STYLE, currentStyle ); } void TMyWindow::CMDemoStyle(RTMessage) { PTStyleWindow StyleWindow = new TStyleWindow( this , "Style demo window" ); GetApplication()->MakeWindow( StyleWindow ); } _CLASSDEF( TClassWindow ) // This window will host a superclassed edit control. class TClassWindow : public TDemoWindow { public: TClassWindow(PTWindowsObject AParent, LPSTR ATitle); }; // This is an example of a superclassed edit control. The steps // are overriding GetClassName, GetWindowClass, and calling // GetClassInfo in GetWindowClass. Note, in general, it is better // if you can find a way to NOT superclass a control. The example // is provided to show you how, but it uses more system resources // to register a new window class, and there is usually a way to // do what you want without super classing. This example changes // the cursor of the edit control, but a better way to do that is // by trapping the WM_SETCURSOR message in a a derived class of TEdit. // Other typically reasons for superclassing are to change the // background and the WndExtra bytes, but the background could be // controled through the WM_CTLCOLOR message, and you can probably // substitute a data member of a TEdit derivative for extra window bytes. class TMyEdit : public TEdit { PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 8/12 TITLE : Customizing the attributes and style of a Window. public: TMyEdit( PTWindowsObject parent, int id , LPSTR text , int x, int y, int w, int h, WORD len, BOOL multi ) : TEdit( parent, id, text, x, y, w, h, len, multi ) {} virtual LPSTR GetClassName() { return "EDIT_MINE"; } virtual void GetWindowClass( WNDCLASS _FAR &wc ); }; void TMyEdit::GetWindowClass( WNDCLASS _FAR &wc ) { memset( &wc , 0, sizeof( wc )); if ( GetClassInfo( NULL , "EDIT", &wc ) == 0 ) MessageBox( GetFocus(), "GetClassInfo failed", "", MB_OK ); // change the cursor of the class (note, WM_SETCURSOR is a // better way to deal with this) wc.hCursor = ( HCURSOR ) LoadCursor( 0 , IDC_SIZEWE ); // these fields were not filled in by GetClassInfo wc.lpszMenuName = NULL; wc.lpszClassName = TMyEdit::GetClassName(); } TClassWindow::TClassWindow( PTWindowsObject AParent, LPSTR title ) : TDemoWindow( AParent, title ) { // save old attributes TWindowAttr a = edit->Attr; delete edit; edit = new TMyEdit( this , a.Id , 0, a.X, a.Y, a.W, a.H, 0, 0 ); } void TMyWindow::CMDemoClassChange(RTMessage) { PTClassWindow ClassWindow = new TClassWindow( this , "Class demo window" ); GetApplication()->MakeWindow( ClassWindow ); } _CLASSDEF( TSetCursorWindow ) PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 9/12 TITLE : Customizing the attributes and style of a Window. // A window which traps the WM_SETCURSOR message to change the cursor in // the window. class TSetCursorWindow : public TDemoWindow { public: TSetCursorWindow(PTWindowsObject AParent, LPSTR ATitle); virtual void WMSetCursor( RTMessage ) = [ WM_FIRST + WM_SETCURSOR ]; }; TSetCursorWindow::TSetCursorWindow(PTWindowsObject AParent, LPSTR ATitle ) : TDemoWindow( AParent , ATitle ) { } void TSetCursorWindow::WMSetCursor( RTMessage msg ) // The way this message works is that it first gets sent to parent // windows, and then to children till someone returns TRUE to halt // processing. We check the WParam here because the cursor may be // over a child window and we don't want to change its cursor. { if ( (HWND)msg.WParam == HWindow ) { SetCursor( ( HCURSOR )LoadCursor( 0 , IDC_CROSS ) ); msg.Result = TRUE; } else DefWndProc( msg ); } void TMyWindow::CMDemoWMSetCursor(RTMessage) { PTSetCursorWindow CursorWindow = new TSetCursorWindow( this , "WM_SETCURSOR demo window" ); GetApplication()->MakeWindow( CursorWindow ); } _CLASSDEF( TSetBackgroundWindow ) // traps WM_ERASEBKGND to change the background of the window. hit // the left mouse button to get a new background. class TSetBackgroundWindow : public TDemoWindow { PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 10/12 TITLE : Customizing the attributes and style of a Window. public: TSetBackgroundWindow(PTWindowsObject AParent, LPSTR ATitle); virtual void WMEraseBkgnd( RTMessage ) = [ WM_FIRST + WM_ERASEBKGND ]; virtual void WMLButtonDown( RTMessage )= [ WM_FIRST + WM_LBUTTONDOWN ]; void GetNewBrush(); ~TSetBackgroundWindow(); HBRUSH hbrush; }; TSetBackgroundWindow::TSetBackgroundWindow(PTWindowsObject AParent, LPSTR ATitle ) : TDemoWindow( AParent , ATitle ) { hbrush = 0; GetNewBrush(); } void TSetBackgroundWindow::WMEraseBkgnd (RTMessage msg ) { RECT rect; GetClientRect( HWindow , &rect ); FillRect( (HDC)msg.WParam , &rect , hbrush ); msg.Result = TRUE; } void TSetBackgroundWindow::WMLButtonDown (RTMessage ) { GetNewBrush(); InvalidateRect( HWindow , NULL , TRUE ); } void TSetBackgroundWindow::GetNewBrush() { if ( hbrush ) DeleteObject ( hbrush ); hbrush = CreateSolidBrush( RGB( rand() % 256 , rand() % 256 , rand() % 256 ) ); } TSetBackgroundWindow::~TSetBackgroundWindow() { if ( hbrush ) DeleteObject( hbrush ); PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 11/12 TITLE : Customizing the attributes and style of a Window. } void TMyWindow::CMDemoBackground(RTMessage) { PTSetBackgroundWindow Background = new TSetBackgroundWindow( this , "Background changing demo window" ); GetApplication()->MakeWindow( Background ); } void TMyApp::InitMainWindow() { MainWindow = new TMyWindow(NULL, Name); } int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { TMyApp MyApp("Sample ObjectWindows Program", hInstance, hPrevInstance, lpCmdLine, nCmdShow); MyApp.Run(); return MyApp.Status; } // // // MODRC.H // // #define CM_DEMO_WM_CTLCOLOR 101 #define CM_DEMO_WM_SETFONT 102 #define CM_DEMO_STYLE 103 #define CM_CLASS_CHANGE 104 #define CM_DEMO_WM_SETCURSOR 105 #define CM_DEMO_BACKGROUND 106 PRODUCT : Borland C++ NUMBER : 1166 VERSION : 3.1 OS : WIN DATE : October 22, 1993 PAGE : 12/12 TITLE : Customizing the attributes and style of a Window. // // MOD.RC // #include "modrc.h" MENU_1 MENU BEGIN POPUP "Demos" BEGIN MENUITEM "WM_CTLCOLOR to change child control colors", CM_DEMO_WM_CTLCOLOR MENUITEM "WM_SETFONT to change the font a control uses", CM_DEMO_WM_SETFONT MENUITEM "SetWindowLong, to change a window style", CM_DEMO_STYLE MENUITEM "WNDCLASS, how to change class info in control", CM_CLASS_CHANGE MENUITEM "WM_SETCURSOR to change the cursor", CM_DEMO_WM_SETCURSOR MENUITEM "WM_ERASEBKGND to paint the background", CM_DEMO_BACKGROUND END END DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.