Tasp
Full Member
Posts: 215
|
Post by Tasp on Oct 31, 2021 9:35:27 GMT -5
I vaguely seem to remember someone found a way of having different coloured statictext on an already opened window, or was I dreaming? ForegroundColor$ = "BLACK" STATICTEXT #m.1, "Question", 100, 100, 75, 25 ForegroundColor$ = "RED" STATICTEXT #m.2, "ANSWER", 200, 100, 75, 25 ForegroundColor$ = "BLACK"
OPEN "Test" FOR WINDOW AS #m #m, "trapclose [quit]" WAIT
[quit] CLOSE #m STOP
And this is my first post in a while that hasn't been about Time Calculations!!
|
|
|
Post by Walt Decker on Oct 31, 2021 11:12:45 GMT -5
I do it, but I change the style to SS_OWNERDRAW and use API to set the color and text. Do you want to go that route?
|
|
|
Post by Walt Decker on Oct 31, 2021 16:01:37 GMT -5
' WS.MINIMIZEBOX = HEXDEC("&H00020000") WS.MAXIMIZEBOX = HEXDEC("&H00010000") WS.THICKFRAME = HEXDEC("&H00040000")
WS.EX.DLGMODALFRAME = HEXDEC("&H00000001")
SS.OWNERDRAW = HEXDEC("&H0000000D")
BRICK = HEXDEC("&H2222B2") PINK = HEXDEC("&HCBC0FF")
OPEN "User32.dll" FOR DLL AS #USER OPEN "gdi32.dll" FOR DLL AS #GDI
STYLEBITS #DMO.LBL, SS.OWNERDRAW, 0, WS.EX.DLGMODALFRAME, 0 STATICTEXT #DMO.LBL, "Unchecked.bmp", 5, 5, 128, 25
UpperLeftX = 100 UpperLeftY = 100 WindowWidth = 326 WindowHeight = 300
STYLEBITS #DMO, 0, WS.MINIMIZEBOX OR WS.MAXIMIZEBOX OR WS.THICKFRAME, 0, 0 OPEN "BUTTON IMAGE" FOR WINDOW AS #DMO PRINT #DMO, "TRAPCLOSE [CLOSE.DMO]"
LblHndl = HWND(#DMO.LBL) TxtLen = FN.GetTextLen(LblHndl) TxtIn$ = FN.GetText$(LblHndl, TxtLen, TxtIn$)
PRINT TxtIn$, TxtLen RetVal = FN.RenderStatic(LblHndl, BRICK, PINK, TxtLen, TxtIn$) WAIT
[END.WAIT] END
'--------------------------------------------------------------- '---------------------------------------------------------------
[CLOSE.DMO]
CLOSE #USER CLOSE #GDI CLOSE #DMO
GOTO [END.WAIT] [END.CLOSE.DMO]
'--------------------------------------------------------------- '---------------------------------------------------------------
FUNCTION FN.ClientRect(WinHndl, BYREF Bx, BYREF By) '######################################################### ' Retrive the client area of a window. ' Since the upper left corner of the client area is always ' zero, zero the lower left corner only is of importance '###########################################################
STRUCT tRect, _ X AS LONG, _ Y AS LONG, _ X1 AS LONG, _ Y1 AS LONG
RetVal = 0 CALLDLL #USER, "GetClientRect", WinHndl AS ULONG, tRect AS STRUCT, _ RetVal AS VOID Bx = tRect.X1.struct By = tRect.Y1.struct END FUNCTION
'------------------------------------------------------------ '------------------------------------------------------------
FUNCTION FN.GetDc(WinHndl) '############################################################# ' retrieve a device context from the MS Win system '#############################################################
WinDc = 0 CALLDLL #USER, "GetDC", WinHndl AS ULONG, WinDc AS ULONG
FN.GetDc = WinDc END FUNCTION
'--------------------------------------------------------------- '---------------------------------------------------------------
FUNCTION FN.AttachObj(WinDc, ThisObject) '############################################################ ' Equate an object (bitmap, brush, pen, font) with a ' device. '############################################################
OrgObj = 0 CALLDLL #GDI, "SelectObject", WinDc AS ULONG, ThisObject AS ULONG, _ OrgObj AS ULONG
FN.AttachObj = OrgObj END FUNCTION
'--------------------------------------------------------------- '---------------------------------------------------------------
FUNCTION FN.DetachDc(WinHndl, WinDc) '################################################################## ' Deactivate a device '##################################################################
RetVal = 0 CALLDLL #USER, "ReleaseDC", WinHndl AS ULONG, WinDc AS ULONG, RetVal AS VOID END FUNCTION
'--------------------------------------------------------------- '---------------------------------------------------------------
FUNCTION FN.KillObj(ThisObj) '####################################################### ' Destroy the object to release MS Win resources and ' prevent over-flow. '########################################################
DeadObj = 0 CALLDLL #GDI, "DeleteObject", ThisObj AS ULONG, DeadObj AS VOID
END FUNCTION
'--------------------------------------------------------------- '---------------------------------------------------------------
FUNCTION FN.GetTextLen(WinHndl)
TxtLen = 0 CALLDLL #USER, "GetWindowTextLengthA", WinHndl AS ULONG, TxtLen AS LONG
FN.GetTextLen = TxtLen + 1 END FUNCTION
'------------------------------------------------------------------ '------------------------------------------------------------------
FUNCTION FN.GetText$(WinHndl, TxtLen, TxtIn$)
TxtIn$ = SPACE$(TxtLen) CALLDLL #USER, "GetWindowTextA", WinHndl AS ULONG, TxtIn$ AS PTR, _ TxtLen AS LONG, TxtLen AS LONG
FN.GetText$ = TxtIn$ END FUNCTION
'------------------------------------------------------------- '-------------------------------------------------------------
FUNCTION FN.SolidBrush(FillColor) '########################################################### ' Creats a fill bitmap of the specified color '###########################################################
BrushHndl = 0 CALLDLL #GDI, "CreateSolidBrush", FillColor AS ULONG, BrushHndl AS ULONG
FN.SolidBrush = BrushHndl END FUNCTION
'------------------------------------------------------------------------ '------------------------------------------------------------------------
FUNCTION FN.TextColor(WinDc, TxtColor) '####################################################### ' Set text color and return original color '#######################################################
OldColor = 0
CALLDLL #GDI, "SetTextColor", WinDc AS ULONG, TxtColor AS ULONG, _ OldColor AS ULONG
FN.TextColor = OldColor END FUNCTION
'------------------------------------------------------------------ '------------------------------------------------------------------
FUNCTION FN.RenderMode(WinDc, Mode) '############################################################# ' Set the render mode for broken lines and text ' If Mode is TRANSPARENT the background color shows through ' the spaces between broken lines and text characters '#############################################################
OldMode = 0 CALLDLL #GDI, "SetBkMode", WinDc AS ULONG, Mode AS LONG, OldMode AS LONG
FN.RenderMode = OldMode END FUNCTION
'--------------------------------------------------------------------- '---------------------------------------------------------------------
FUNCTION FN.GetFontHndl(WinHndl)
WM.GETFONT = HEXDEC("&H0031")
FontHndl = -1
CALLDLL #USER, "SendMessageA", WinHndl AS ULONG, WM.GETFONT AS ULONG, _ 0 AS LONG, 0 AS LONG, FontHndl AS ULONG
FN.GetFont = FontHndl END FUNCTION
'------------------------------------------------------------------------- '-------------------------------------------------------------------------
FUNCTION FN.RenderStatic(WinHndl, BkgColor, TxtColor, TxtLen, TxtOut$)
TRANSPARENT = 1
DT.CENTER = HEXDEC("&H00000001") DT.VCENTER = HEXDEC("&H00000004") DT.SINGLELINE = HEXDEC("&H00000020") DT.TXT = DT.CENTER OR DT.VCENTER OR DT.SINGLELINE
RetVal = 0 WinDc = 0
Brush = 0 FntHndl = 0 OldBrsh = 0 OldMode = 0 OldTxt = 0
Bx = 0 By = 0
RetVal = FN.ClientRect(WinHndl, Bx, By) Brush = FN.SolidBrush(BkgColor) FntHndl = FN.GetFontHndl(WinHndl)
WinDc = FN.GetDc(WinHndl)
CALLDLL #USER, "FillRect", WinDc AS ULONG, tRect AS STRUCT, _ Brush AS ULONG, RetVal AS LONG RetVal = FN.KillObj(Brush) OldMode = FN.RenderMode(WinDc, TRANSPARENT) OldTxt = FN.TextColor(WinDc, TxtColor)
CALLDLL #USER, "DrawTextA", WinDc AS ULONG, TxtOut$ AS PTR, TxtLen AS LONG, _ tRect AS STRUCT, DT.TXT AS ULONG, RetVal AS LONG
OldMode = FN.RenderMode(WinDc, OldMode) OldTxt = FN.TextColor(WinDc, OldTxt) RetVal = FN.DetachDc(WinHndl, WinDc)
END FUNCTION '
|
|
dkl
Full Member
Posts: 234
|
Post by dkl on Oct 31, 2021 22:35:00 GMT -5
I use disabled bmpButtons with a coloured.bmp file. Then place them use on top of each other and use #1.1,"show/hide" to change between them. Works fine! Just a thought
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Nov 1, 2021 13:17:18 GMT -5
Thanks Walt for the demo, I see where you're going with this and it's interesting.
dkl, thanks for the input, this wouldn't work for me as the text dynamically changes. If I went down the track, I could just place a graphics box on the window and change the colour to anything I liked.
|
|
|
Post by Walt Decker on Nov 1, 2021 15:13:15 GMT -5
Be aware of several things:
1. When the SS.USERDRAW style is used LB displays "<User Drawn>" in the static control rather than the actual text passed to it. This allows you to set your own font without using the LB set font function.
2. The FN.GetFontHndl() function only returns the system font, not the font used by LB for the static control. Therefore, the text length may or may not fit within the control. Your best bet is to create your own font and use the gdi function GetTextExtentPoint32() to determine if your text will fit in the control.
3. If the form window, i. e. the window containing the control, is resized you will have to refresh the control yourself.
If you decide to use this approach, and need more info, most of this is in the "Things You Do Not Want to Know ... " series, General Discussion thread, or let me know here. I will give you a hand.
|
|
|
Post by Chris Iverson on Nov 2, 2021 20:13:51 GMT -5
If you're willing to use an external DLL, I might recommend using one to subclass the LB window to respond to the WM_CTLCOLORSTATIC window message, which lets you set the color of a specific statictext window. I could modify a DLL I already have that does the same thing for text boxes; it'd be dead simple to modify it to handle statictexts, because the logic is the same. The only difference is which window message is watched for(WM_CTLCOLORSTATIC for statictexts, and WM_CTLCOLOREDIT for edit boxes). See my post here for an example of how that worked from the point of view of LB code: libertybasiccom.proboards.com/post/11314/threadEDIT: Here's a second example with the DLL, showing more colors, and how they can change on the fly: libertybasiccom.proboards.com/post/10884/thread
|
|
|
Post by Walt Decker on Nov 3, 2021 9:08:10 GMT -5
Using a sub-classing dll is a good idea. The WM_CTLCOLOR... message triggers a MSWIN routine that does essentially the same thing as the RenderStatic() function in my demo with the added bonus of not having to refresh the static control yourself. One thing that comes to mind is a dll that reads the property sheet of each control and sets the text and background colors based on the values found. That way only the property keys would have to be passed to the dll on initialization. Each of the controls would have the same keys but different values for each key. The programmer could then change the colors at any time by simply changing the values in the property sheet.
Edit:
Example:
CALLDLL #STAT, "InitCtl", "Txt" AS PTR, "BKG" AS PTR, RetVal AS VOID CALLDLL #STAT, "AddStatic", StatHndl.1 AS ULONG, RetVal AS VOID CALLDLL #STAT, "AddStatic", StatHndl.2 AS ULONG, RetVal AS VOID
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Nov 6, 2021 10:06:37 GMT -5
Sorry for the delay in response.
I'm always happy to use any means necessary to make something work!
And the DLL route appears a simpler way to change the colour on the fly.
Chris, if it's not too much trouble to modify your DLL that would be awesome! At this rate all this programs supporting files are going to be supplied by you!
Walt, yes I did stumble across the font issue. But managed to resolve it. I think using a DLL call, is a simple one line transaction, would be the way forward.
|
|
|
Post by Walt Decker on Nov 6, 2021 13:24:38 GMT -5
|
|