How to create a color form in BP?

BlitzPlus Forums/BlitzPlus Programming/How to create a color form in BP?

William Miller(Posted 2004) [#1]
Ayy ideas on how to create a form with a background color that differs from the standard 'system' color? I know the 'SetSysColors' does this in the Win32 API, but if it is possible to use this for BP, what values would one pass to the function, and how?

Here is the .decls for this function:

api_SetSysColors% (nChanges%, lpSysColor%, lpColorValues%)

I believe the 'lpSysColor' value would be:
COLOR_APPWORKSPACE as listed by the API-Guide, but I havent a clue on the other values, or how one would use them in this case.

TIA,

WM


soja(Posted 2004) [#2]
You've done most of the work already.

Have you looked it up on MSDN? It will tell you what the parameters mean, and also what library it's in (e.g. kernel32.dll, user32.dll, etc)

As for setting the background color, you'll have to use GDI functions FillRect (I think), GetDC, etc. You'll also have to do it once per frame unless you can catch the WM_PAINT messages.

I've got an example -- I did this once -- but not on this computer.


William Miller(Posted 2004) [#3]
Soja,

The function is in user32.dll, I have the function in the user32.decls file in my userlib, and indeed I do have the function added in the code itself --it will compile, but it does nothing as I really don't know how or what values to pass to it. The function takes 3 parameters: for example the third function parameter is a 3-part RGB color code: RGB(x,x,x). But how do I pass that 3-part color value into that parameter in the function in BP? I cant simply enter the 3 numbers, of course. Passing it a 3-eleement array with the 3 color values might work, but how exactly would one do that?

Thanks,
WM


soja(Posted 2004) [#4]
Hi,

Well, let me answer some of your questions first. As you see in the documentation on MSDN, the third parameter is a *pointer* to a COLORREF type. We don't know what that is at this point, but we do know that since it's a pointer, we should pass either a bank or a type object and declare the paramter in the decls file with * (not % or $). As for the COLORREF type (which exists in Win32 but not Blitz, obviously), just click on the COLORREF link from the docs. That takes you to the definition, and lo and behold, we find that COLORREF is the exact same thing as a DWORD, and a DWORD is simply two WORDs, 4 bytes, or 32 bits. You can also see that the lowest byte stores the red value (0-255), the second lowest byte stores the green, the third the blue, and the fourth is not used here.

So an example, to pass yellow:
Declare the lpColorValues parameter as * (not %) in the decls.
Then in your program, do one of these:
cv=CreateBank(3)
PokeByte(cv, 3, $FF)
PokeByte(cv, 2, $FF)

type ColorValue : Field cv% : End Type
cv.ColorValue = New ColorValue
cv\cv = ($ff Shl 8) Or $ff ; Creates $0000FFFF = Yellow

...then when you call it, just pass cv as the third param.

THAT SAID...
By all means, try it out and see if you can get it to work (learning and stuff), but I don't think you should use this function for what you're doing. You'll end up changing the color of ALL your windows.

You'll have to use GDI to do what you want, like I mentioned briefly before. I should probably see the example of how I did it before to help help you though (it's at home)


<EDIT> Note, if the function didn't require a pointer as the third parameter, you could have just used an int% (since a COLORREF is just 4 bytes = int), but since it's a pointer, that why we have to "enclose" the int within a bank or type object.


soja(Posted 2004) [#5]
Here's one way to do it. If anybody has another way of doing it, please share!
; .lib "gdi32.dll"
; Rectangle%(hdc%, l, t, r, b):"Rectangle"
; GetStockObject%(fnObject%):"GetStockObject"
; SetDCBrushColor%(hdc%, crColor%):"SetDCBrushColor"
; SelectObject%(hdc, hgdiobj%):"SelectObject"

Const DC_BRUSH = 18
Global wndMain=CreateWindow("",200,200,200,200)
Global btn=CreateButton("Hello", 10, 10, 100, 20, wndMain)

CreateTimer(60)
Repeat
	Select WaitEvent()
		Case $803 : End
		Case $4001 : DrawBG()
	End Select
Forever

Function DrawBG() ; Low-CPU GDI calls
	dc% = GetDC(QueryObject(wndMain,1)) : If Not dc Then Return ; Fail
	SelectObject(dc, GetStockObject(DC_BRUSH))
	SetDCBrushColor(dc, $cccc) ; Mustard yellow
	Rectangle(dc,0,0,GadgetWidth(wndMain),GadgetHeight(wndMain))
	ReleaseDC(QueryObject(wndMain,1), dc)
End Function



William Miller(Posted 2004) [#6]
Soja,

That does work, at least in the test window, but using it
in my application causes it to crash with a heap error.

A friend of mine has a good lead on another possible method to do this, I will talk to him and post what he comes up with here if it works as I hope it does.

Thanks!
WM


soja(Posted 2004) [#7]
Make sure that your window gadget handle is global... if it isn't, that would cause a crash.


William Miller(Posted 2004) [#8]
Soja,

All my window handles & gadgets are declared Global -- I believe the crash issue has to do with the sequencing of how several of the window forms and gadgets in my project are created. For now I am continuing on with the main project work itself, and I will revist the color-forms issue at a later date, since the color-form issue is not a high-priority goal in the work.

Thanks for your kind assistance!
WM


skidracer(Posted 2004) [#9]
http://www.blitzbasic.com/codearcs/codearcs.php?code=596


soja(Posted 2004) [#10]
Brilliant, you can change the color of a panel. Much easier than using GDI directly.


William Miller(Posted 2004) [#11]
Skidracer & Soja,

Yes, that one I already tried...but text labels still have the default grey background under them, which makes my forms look rather tacky I'm afraid, as I have a number of text labels on the forms. If it were not for that, this would be a near-perfect solution indeed...

Thanks,
WM