I tried to make a simple program to skin any window.. I used this code:
Code:
Dim DC As Long
Dim hWnd As Long
Dim Temp As Rect
hWnd = Window(SelectedWindow).hWnd
'Get rect
GetClientRect hWnd, Temp
DC = GetWindowDC(hWnd)
'Setup rect
Temp.Left = Temp.Left + 4
Temp.Top = Temp.Top + 4
Temp.Right = Temp.Right - Temp.Left + 4
Temp.Bottom = Temp.Bottom - Temp.Top + 4
'Copy picture
With Temp: BitBlt DC, .Left, .Top, .Right, .Bottom, Front.hDC, 0, 0, vbSrcCopy: End With
The code actually works, see the screenshot:
However, can you help me with this?
How can I get the offset (4 in the example) from windows?
Any way to only paint into the BG of the window? (not over controls)
How to keep the picture there? (enabled "AutoRedraw" for that window)
Use a big freakin while loop to check the color of a GetPixel(). If it is a certain color, SetPixelV from your skin image. It works wonders, but it is slow =(.
I dont know if you can create a GDI brush that is an image, but if you can, do that, and use SetClassLong with GCL_HBRBACKGROUND, and the Brush handle =).
I think that, to set AutoRedraw on a window, use Get- and SetClassLong, Get the current Style (GCL_STYLE), bit-or it with CS_SAVEBITS, and set it back.
SetPixelling is too slow and the API cant handle pictures as brushed... and the SaveBits thingy wont work neither (tried it, just draws into the titlebar then..)
Create a system wide message hook and override the paint messages? Would be a real challenge in VB
Or, if you only want certain windows, you could try to override just the windowproc using SetWindowLong with GWL_WNDPROC, then draw your background whenever a paint message comes by... again, highly unstable in VB
Either way, it's going to be tricky...
Now for your list:
"How can I get the offset (4 in the example) from windows?"
Is there anything special with that offset that is the same for every window you want to paint? Are the controls that much off the border?
"Any way to only paint into the BG of the window? (not over controls)"
WM_ERASEBKGND ?
"How to keep the picture there? (enabled "AutoRedraw" for that window)"
If you override the paint procedures you can just redraw it every time, thus emulating the AutoRedraw thing...
Teaudirenopossum.Musasapientumfixaestinaure. (I can't hear you. There's a banana in my ear)
Originally posted by Fox I just noticed a normal window's frame size is 4 pixels, but i'd rather get a distance from the registry 'coz the user might have changed it.
I think GetClientRect should get the correct size (excluding the border), although you use it and still have to add 4 pixels. Weird...
Originally posted by Fox > WM_ERASEBKGND ?
With BitBlt?
The problem is, you can paint as much background as you want, unless your controls are transparant you won't see much
With the 'My Computer' window, you can try to find the ListView and set a transparancy style (if it exists) or simply use the ListView for overriding the paint methods. For other windows it would be somewhat more difficult...
Originally posted by Fox > If you override the paint procedures you can
> just redraw it every time, thus emulating
> AutoRedraw thing...
Sounds good, but too instable to implement..
I know, but I though I'd just let you know the way I would try to do it.... although I stopped thinking in VB terms a while ago
[edit] typo
Teaudirenopossum.Musasapientumfixaestinaure. (I can't hear you. There's a banana in my ear)
The CreatePatternBrush function creates a logical brush with the specified bitmap pattern. The bitmap cannot be a DIB section bitmap, which is created by the CreateDIBSection function.
HBRUSH CreatePatternBrush(
HBITMAP hbmp // handle to bitmap
);
Parameters
hbmp
Identifies the bitmap to be used to create the logical brush.
Windows 95: Creating brushes from bitmaps or DIBs larger than 8x8 pixels is not supported. If a larger bitmap is specified, only a portion of the bitmap is used.
So it IS possible to use bitmap brushes, but they would be 8x8 max. on Win9x
(I just love the Win32 SDK help files that came with Delphi )
Teaudirenopossum.Musasapientumfixaestinaure. (I can't hear you. There's a banana in my ear)
Sorry for yet another post, but I just found something interesting:
The GetSystemMetrics function retrieves various system metrics and system configuration settings.
System metrics are the dimensions (widths and heights) of Windows display elements. All dimensions retrieved by GetSystemMetrics are in pixels.
int GetSystemMetrics(
int nIndex // system metric or configuration setting to retrieve
);
nIndex
Specifies the system metric or configuration setting to retrieve. All SM_CX* values are widths. All SM_CY* values are heights. The following values are defined:
*cut*
SM_CXBORDER,
SM_CYBORDER The width and height, in pixels, of a window border. This is equivalent to the SM_CXEDGE value for windows with the 3-D look.
So there's the answer to question #1
Teaudirenopossum.Musasapientumfixaestinaure. (I can't hear you. There's a banana in my ear)
You could get an image of the window (bitblt), try to get a DIB (that's the fast array thing right?) from it and bitblt it back after you've manipulated the array...
Don't have a clue on how to do that though, never really needed it
...or you could download WindowBlinds
(although that's not half as much fun )
Teaudirenopossum.Musasapientumfixaestinaure. (I can't hear you. There's a banana in my ear)