User Tools

Site Tools


changing_20a_20control_27s_20colours

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

changing_20a_20control_27s_20colours [2018/03/31 13:19]
127.0.0.1 external edit
changing_20a_20control_27s_20colours [2018/04/15 17:15] (current)
richardrussell Added syntax highlighting
Line 1: Line 1:
 =====Changing a control'​s colours===== =====Changing a control'​s colours=====
  
-//by Richard Russell, September 2007//\\ \\  You will normally want dialogue box controls to use their default colour scheme, for reasons of uniformity with other Windows applications,​ but occasionally you may want to change the foreground and/or background colours for special purposes. There are a number of techniques that can be used to achieve this, for example you can create a coloured Edit Box by using a [[/​Using%20Rich%20Edit%20controls|Rich Edit control]] or you can create a coloured Static Control by drawing into a suitable bitmap and displaying it in a [[/​Displaying%20a%20JPEG%20or%20GIF%20in%20a%20picture%20box|picture box]] or you can use a [[/​Creating%20a%20custom%20graphics%20control|custom graphics control]].\\ \\  This article describes an alternative technique, involving subclassing the dialogue box using the **SUBCLASS.BBC** library (version 1.3 or later). In some ways it is more flexible than the other methods, since it allows you to change the colours of other controls, not just Text Boxes and Static Controls. To illustrate the effect the program listed below creates this rather garish dialogue box:\\ \\ {{garish.gif}}\\ \\  Firstly we need to install a couple of libraries and define some constants:\\ +//by Richard Russell, September 2007//\\ \\  You will normally want dialogue box controls to use their default colour scheme, for reasons of uniformity with other Windows applications,​ but occasionally you may want to change the foreground and/or background colours for special purposes. There are a number of techniques that can be used to achieve this, for example you can create a coloured Edit Box by using a [[/​Using%20Rich%20Edit%20controls|Rich Edit control]] or you can create a coloured Static Control by drawing into a suitable bitmap and displaying it in a [[/​Displaying%20a%20JPEG%20or%20GIF%20in%20a%20picture%20box|picture box]] or you can use a [[/​Creating%20a%20custom%20graphics%20control|custom graphics control]].\\ \\  This article describes an alternative technique, involving subclassing the dialogue box using the **SUBCLASS.BBC** library (version 1.3 or later). In some ways it is more flexible than the other methods, since it allows you to change the colours of other controls, not just Text Boxes and Static Controls. To illustrate the effect the program listed below creates this rather garish dialogue box:\\ \\ {{garish.gif}}\\ \\  Firstly we need to install a couple of libraries and define some constants: 
 + 
 +<code bb4w>
         INSTALL @lib$+"​WINLIB2"​         INSTALL @lib$+"​WINLIB2"​
         INSTALL @lib$+"​SUBCLASS"​         INSTALL @lib$+"​SUBCLASS"​
Line 14: Line 16:
         WS_GROUP = &20000         WS_GROUP = &20000
         WS_BORDER = &800000         WS_BORDER = &800000
-Note that version 1.3 or later of SUBCLASS.BBC is required.\\ \\  Next we can create the dialogue box template in the usual way:\\ +</​code>​ 
 + 
 +Note that version 1.3 or later of SUBCLASS.BBC is required.\\ \\  Next we can create the dialogue box template in the usual way: 
 + 
 +<code bb4w>
         dlg% = FN_newdialog("​Dialogue box", 20, 20, 160, 128, 8, 560)         dlg% = FN_newdialog("​Dialogue box", 20, 20, 160, 128, 8, 560)
  
Line 21: Line 27:
         PROC_pushbutton(dlg%,​ "​OK",​ 1, 12, 108, 56, 14, WS_GROUP + BS_DEFPUSHBUTTON)         PROC_pushbutton(dlg%,​ "​OK",​ 1, 12, 108, 56, 14, WS_GROUP + BS_DEFPUSHBUTTON)
         PROC_pushbutton(dlg%,​ "​Cancel",​ 2, 92, 108, 56, 14, 0)         PROC_pushbutton(dlg%,​ "​Cancel",​ 2, 92, 108, 56, 14, 0)
-So far everything is conventional,​ but now we sub-class the necessary Windows messages:\\ +</​code>​ 
 + 
 +So far everything is conventional,​ but now we sub-class the necessary Windows messages: 
 + 
 +<code bb4w>
         PROC_subclassdlg(dlg%,​ WM_CTLCOLORLISTBOX,​ FNctlcolorlistbox())         PROC_subclassdlg(dlg%,​ WM_CTLCOLORLISTBOX,​ FNctlcolorlistbox())
         PROC_subclassdlg(dlg%,​ WM_CTLCOLORSTATIC,​ FNctlcolorstatic())         PROC_subclassdlg(dlg%,​ WM_CTLCOLORSTATIC,​ FNctlcolorstatic())
         PROC_subclassdlg(dlg%,​ WM_CTLCOLORDLG,​ FNctlcolorbackgnd())         PROC_subclassdlg(dlg%,​ WM_CTLCOLORDLG,​ FNctlcolorbackgnd())
         PROC_subclassdlg(dlg%,​ WM_CTLCOLORBTN,​ FNctlcolorbackgnd())         PROC_subclassdlg(dlg%,​ WM_CTLCOLORBTN,​ FNctlcolorbackgnd())
-Note that in this particular case the same function is used for both the CTLCOLORDLG and CTLCOLORBTN messages because in each case all we want to do is change the background colour. If you don't change the background colour of the buttons to match the dialogue box background an ugly border around the buttons will be visible.\\ \\  Now we can display the dialogue box and initialise any controls that need it:\\ +</​code>​ 
 + 
 +Note that in this particular case the same function is used for both the CTLCOLORDLG and CTLCOLORBTN messages because in each case all we want to do is change the background colour. If you don't change the background colour of the buttons to match the dialogue box background an ugly border around the buttons will be visible.\\ \\  Now we can display the dialogue box and initialise any controls that need it: 
 + 
 +<code bb4w>
         PROC_showdialog(dlg%)         PROC_showdialog(dlg%)
  
Line 33: Line 47:
         SYS "​SendDlgItemMessage",​ !dlg%, 101, LB_ADDSTRING,​ 0, "​Listbox item 2"         SYS "​SendDlgItemMessage",​ !dlg%, 101, LB_ADDSTRING,​ 0, "​Listbox item 2"
         SYS "​SendDlgItemMessage",​ !dlg%, 101, LB_ADDSTRING,​ 0, "​Listbox item 3"         SYS "​SendDlgItemMessage",​ !dlg%, 101, LB_ADDSTRING,​ 0, "​Listbox item 3"
-Again, this is conventional.\\ \\  Finally we run our main loop which, for the purposes of the exercise, does nothing useful:\\ +</​code>​ 
 + 
 +Again, this is conventional.\\ \\  Finally we run our main loop which, for the purposes of the exercise, does nothing useful: 
 + 
 +<code bb4w>
         ON CLOSE PROC_closedialog(dlg%) : QUIT         ON CLOSE PROC_closedialog(dlg%) : QUIT
         ON ERROR PROC_closedialog(dlg%) : SYS "​MessageBox",​ @hwnd%, REPORT$, 0, 48 : QUIT         ON ERROR PROC_closedialog(dlg%) : SYS "​MessageBox",​ @hwnd%, REPORT$, 0, 48 : QUIT
Line 46: Line 64:
         PROC_closedialog(dlg%)         PROC_closedialog(dlg%)
         END         END
-Note that while subclassing is in effect you must avoid statements which may take a long time to execute, such as **GET**, **INKEY**, **INPUT** and **WAIT** (WAIT should be avoided even if the delay is short). You should also be careful not to use **SOUND** when the sound queue is already full. You can find suitable replacements for these functions in the [[http://​www.bbcbasic.co.uk/​bbcwin/​manual/​bbcwing.html#​nowait|NOWAIT]] library.\\ \\  We mustn'​t forget the vital routines that handle the subclassing:​\\ +</​code>​ 
 + 
 +Note that while subclassing is in effect you must avoid statements which may take a long time to execute, such as **GET**, **INKEY**, **INPUT** and **WAIT** (WAIT should be avoided even if the delay is short). You should also be careful not to use **SOUND** when the sound queue is already full. You can find suitable replacements for these functions in the [[http://​www.bbcbasic.co.uk/​bbcwin/​manual/​bbcwing.html#​nowait|NOWAIT]] library.\\ \\  We mustn'​t forget the vital routines that handle the subclassing:​ 
 + 
 +<code bb4w>
         DEF FNctlcolorbackgnd(M%,​ W%, L%)         DEF FNctlcolorbackgnd(M%,​ W%, L%)
         PRIVATE B%         PRIVATE B%
Line 65: Line 87:
         IF B%=0 SYS "​CreateSolidBrush",​ &663366 TO B%         IF B%=0 SYS "​CreateSolidBrush",​ &663366 TO B%
         =B%         =B%
-The colours are here specified in the usual Windows hexadecimal "​BBGGRR"​ format. For the listbox and the static control both the foreground and background colours are set. You should normally set the text background colour ("​SetBkColor"​) to be the same as the control'​s background colour ("​CreateSolidBrush"​).\\ \\  Note that in the above example **all** controls of a particular type are affected. For example, if the WM_CTLCOLORSTATIC message is processed then all Static Controls will change colour. If you want to change the colour of only a subset of the controls of a given type, or give them different colours, then you can test the control'​s handle and act accordingly:​\\ +</​code>​ 
 + 
 +The colours are here specified in the usual Windows hexadecimal "​BBGGRR"​ format. For the listbox and the static control both the foreground and background colours are set. You should normally set the text background colour ("​SetBkColor"​) to be the same as the control'​s background colour ("​CreateSolidBrush"​).\\ \\  Note that in the above example **all** controls of a particular type are affected. For example, if the WM_CTLCOLORSTATIC message is processed then all Static Controls will change colour. If you want to change the colour of only a subset of the controls of a given type, or give them different colours, then you can test the control'​s handle and act accordingly:​ 
 + 
 +<code bb4w>
         DEF FNctlcolorstatic(M%,​ W%, L%)         DEF FNctlcolorstatic(M%,​ W%, L%)
         CASE L% OF         CASE L% OF
Line 75: Line 101:
         ENDCASE         ENDCASE
         =B%         =B%
-Here **hStatic1%** is a global variable containing the handle of the particular Static Control whose colour needs to be changed. Because that handle isn't known until after you have shown the dialogue box, you will need to force the static control to redraw itself:\\ +</​code>​ 
 + 
 +Here **hStatic1%** is a global variable containing the handle of the particular Static Control whose colour needs to be changed. Because that handle isn't known until after you have shown the dialogue box, you will need to force the static control to redraw itself: 
 + 
 +<code bb4w>
         SYS "​GetDlgItem",​ !dlg%, 102 TO hStatic1%         SYS "​GetDlgItem",​ !dlg%, 102 TO hStatic1%
         SYS "​InvalidateRect",​ hStatic1%, 0, 0         SYS "​InvalidateRect",​ hStatic1%, 0, 0
 +</​code>​
 +
 Also, remember to initialise **hStatic1%** (e.g. to zero) so you don't get a 'No such variable'​ error when **FNctlcolorstatic** is called for the first time. Also, remember to initialise **hStatic1%** (e.g. to zero) so you don't get a 'No such variable'​ error when **FNctlcolorstatic** is called for the first time.
changing_20a_20control_27s_20colours.txt · Last modified: 2018/04/15 17:15 by richardrussell