IonicWind Software

IWBasic => The Roundtable => Topic started by: sapero on February 17, 2010, 11:08:29 AM

Title: A window with transparent caption
Post by: sapero on February 17, 2010, 11:08:29 AM
This is a tricky code example showing the simplest method to have a window with transparent areas (using alpha channel).
The main window is layered (WS_EX_LAYERED), and opaque (alpha=255). The WS_EX_LAYERED extended styles makes possible to copy pixels from the desktop, but not including our window.
We copy the desktop pixels from a rectangle where our window resides into temporary device context, per pixel alpha-blend it with previously saved window pixels, and then the result is copied on main window.

If you add a grow (caption text) and blur (caption) effects, it will be a real aero :)

$include "windowssdk.inc"
$use "msimg32.lib"
$define CLIENT_ALPHA 255
$define NONCLIENT_ALPHA 128

main()
end


sub width(pointer rc),int
settype rc,WINRECT
return *rc.right - *rc.left
endsub

sub height(pointer rc),int
settype rc,WINRECT
return *rc.bottom - *rc.top
endsub

sub DrawMe(HWND hwnd, HDC hdcOrigin, HDC hdcTemp)

WINRECT rc
BLENDFUNCTION bf
HDC hdcDesktop = GetDC(0)
HDC hdcWindow =  GetWindowDC(hwnd)

bf.BlendOp = AC_SRC_OVER
bf.BlendFlags = 0
bf.AlphaFormat = AC_SRC_ALPHA
bf.SourceConstantAlpha = 255

GetWindowRect(hwnd, &rc)
int w = width(&rc)
int h = height(&rc)
' copy from desktop bitmap to temporary bitmap
BitBlt(hdcTemp, 0, 0, w, h, hdcDesktop, rc.left, rc.top, SRCCOPY)
' blend the original window bitmap onto temporary bitmap
AlphaBlend(hdcTemp, 0, 0, w, h, hdcOrigin, 0, 0, w, h, bf)
' show the result
BitBlt(hdcWindow, 0, 0, w, h, hdcTemp, 0, 0, SRCCOPY)

ReleaseDC(hwnd, hdcWindow)
ReleaseDC(0, hdcDesktop)
endsub

sub MyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam),BOOL

HDC _hdcOrigin = GetProp(hwnd, "_hdcOrigin")' window bitmap with alpha pixels
HDC _hdcTemp = GetProp(hwnd, "_hdcTemp")

select (uMsg)

case WM_WINDOWPOSCHANGED:
pointer pos = *<WINDOWPOS>lParam
settype pos,WINDOWPOS
' if the window is showing and the variables are not initialized yet
if ((*pos.flags & SWP_SHOWWINDOW) and !_hdcOrigin)

WINDOWINFO wi
BITMAPINFOHEADER bh
pointer pixels
settype pixels, RGBQUAD
POINT pt
HDC hdc = GetWindowDC(hwnd)

wi.cbSize = len(wi)
GetWindowInfo(hwnd, wi)

ZeroMemory(&bh, len(bh))
bh.biSize     = len(bh)
bh.biWidth    = width(&wi.rcWindow)
bh.biHeight   = height(&wi.rcWindow)
bh.biPlanes   = 1
bh.biBitCount = 32

' create window bitmap
_hdcOrigin = CreateCompatibleDC(hdc)
DeleteObject(SelectObject(_hdcOrigin, CreateDIBSection(_
hdc, &bh, DIB_RGB_COLORS, &pixels, 0, 0)))
' remember current window bits
BitBlt(_hdcOrigin, 0, 0, width(&wi.rcWindow), height(&wi.rcWindow), hdc, 0, 0, SRCCOPY)

' temporary bitmap for drawing
_hdcTemp = CreateCompatibleDC(hdc)
DeleteObject(SelectObject(_hdcTemp, CreateCompatibleBitmap(_
hdc, width(&wi.rcWindow), height(&wi.rcWindow))))

ReleaseDC(0, hdc)
SetProp(hwnd, "_hdcOrigin", _hdcOrigin)
SetProp(hwnd, "_hdcTemp", _hdcTemp)

' initialize alpha pixels
int left = wi.rcClient.left - wi.rcWindow.left
int top  = wi.rcClient.top - wi.rcWindow.top
SetRect(&wi.rcClient, left, top, left+width(&wi.rcClient), top+height(&wi.rcClient))

for pt.y=0 to bh.biHeight-1

int y = bh.biHeight - pt.y - 1
pointer lineptr = &*pixels[y * bh.biWidth]
settype lineptr, RGBQUAD

for pt.x=0 to bh.biWidth-1
*lineptr[pt.x].rgbReserved = IIF(PtInRect(&wi.rcClient, pt), CLIENT_ALPHA, NONCLIENT_ALPHA)
next pt.x
next pt.y
endif
DrawMe(hwnd, _hdcOrigin, _hdcTemp)

case WM_CLOSE
DestroyWindow(hwnd)

case WM_DESTROY:
if (_hdcOrigin)
DeleteDC(_hdcOrigin)
DeleteDC(_hdcTemp)
RemoveProp(hwnd, "_hdcOrigin")
RemoveProp(hwnd, "_hdcTemp")
endif
PostQuitMessage(0)

case WM_MOVE
case& WM_NCACTIVATE
case& WM_ACTIVATE
case& WM_ACTIVATEAPP
case& WM_MOUSEACTIVATE
case& WM_NCLBUTTONDOWN
case& 0x02A2
case& WM_SIZING
DrawMe(hwnd, _hdcOrigin, _hdcTemp)
endselect
return FALSE
endsub

sub main()

MSG msg
' open invisible dialog
HWND hwnd = CreateWindowExA(WS_EX_LAYERED, WC_DIALOG, "Transparent Caption", WS_CAPTION|WS_SYSMENU|WS_BORDER,0,0,0,0,0,0,0,0)
' make it opaque
SetLayeredWindowAttributes(hwnd, 0, 255, LWA_ALPHA)
' set message callback function
SetWindowLong(hwnd, DWL_DLGPROC, &MyWndProc)
' show it
SetWindowPos(hwnd,0,200,200,400,300,SWP_NOZORDER|SWP_SHOWWINDOW)

while (GetMessage(&msg, 0, 0, 0))
TranslateMessage(&msg)
DispatchMessage(&msg)
endwhile
return 0
endsub
Title: Re: A window with transparent caption
Post by: pistol350 on February 17, 2010, 02:16:49 PM
Hi Sapero!
I keep getting this message whenever i try to compile the code

"no appropriate conversion exists - )"

The message is related to the line 67 : GetWindowInfo(hwnd, &wi)
Title: Re: A window with transparent caption
Post by: sapero on February 17, 2010, 03:57:24 PM
Maybe I have updated my headers without uploading them, one of the old defines it (winuser.inc) as declare import,GetWindowInfo(HWND hwnd,WINDOWINFO pwi),BOOL

So you can replace the line with GetWindowInfo(hwnd, wi)
Title: Re: A window with transparent caption
Post by: Haim on February 17, 2010, 09:39:34 PM
Hi
It works fine on my laptop without any change.
Thanks for sharing this,
Haim
Title: Re: A window with transparent caption
Post by: ZeroDog on February 17, 2010, 09:51:29 PM
I wanted to try this out... but the windowssdk.inc is like 10megs and im on dial up.... lol. 
Title: Re: A window with transparent caption
Post by: Copex on February 18, 2010, 04:17:38 AM
Quote from: ZeroDog on February 17, 2010, 09:51:29 PM
I wanted to try this out... but the windowssdk.inc is like 10megs and im on dial up.... lol. 

PM your address and i will pop it on a cd and post it to you, if there is anything else you are after just let me know ill happily download and fill CD :-)
Title: Re: A window with transparent caption
Post by: pistol350 on February 18, 2010, 04:55:31 AM
Quote from: sapero on February 17, 2010, 03:57:24 PM
Maybe I have updated my headers without uploading them, one of the old defines it (winuser.inc) as declare import,GetWindowInfo(HWND hwnd,WINDOWINFO pwi),BOOL

So you can replace the line with GetWindowInfo(hwnd, wi)

This worked!
Thanks!
Title: Re: A window with transparent caption
Post by: ZeroDog on February 18, 2010, 01:11:20 PM
QuotePM your address and i will pop it on a cd and post it to you, if there is anything else you are after just let me know ill happily download and fill CD :-)

That is very generous of you, however,  I can either wait till im back on highspeed, or leave it downloading for an hour an a half on dial up.  I was just surprised at the size of the windowssdk.inc... whats in that thing anyways?  must be quite a bit to fill up 10 megs of source code...
Title: Re: A window with transparent caption
Post by: sapero on February 18, 2010, 03:02:25 PM
For today, include directory is 31MB (after a fresh cleanup), additional static libs 29MB (28,5 MB from Microsoft).
Let's see how it grows after adding dxsdk from february 2010 :)
Title: Re: A window with transparent caption
Post by: ckoehn on February 19, 2010, 07:57:34 AM
sapero,

The link that I am sent to is only 11.4MB.   Is there a different one that is the latest?

Thanks,
Clint
Title: Re: A window with transparent caption
Post by: sapero on February 19, 2010, 08:52:45 AM
The latest pak is from 11 july 2009. I have a queued update with the latest DirectX, old directx media, and some bugfixes.