May 15, 2024, 06:14:36 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


A window with transparent caption

Started by sapero, February 17, 2010, 11:08:29 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

sapero

February 17, 2010, 11:08:29 AM Last Edit: February 17, 2010, 03:59:46 PM by sapero
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

pistol350

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)
Regards,

Peter B.

sapero

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)

Haim

Hi
It works fine on my laptop without any change.
Thanks for sharing this,
Haim

ZeroDog

I wanted to try this out... but the windowssdk.inc is like 10megs and im on dial up.... lol. 

Copex

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 :-)
-
I really should learn how to use a spell checker! though im not sure how it will help someone who can not spell?
-
Except where otherwise noted, content Posted By Copex is
licensed under a Creative Commons Attribution 3.0 License

http://creativecommons.org/licenses/by/3.0/

pistol350

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!
Regards,

Peter B.

ZeroDog

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...

sapero

February 18, 2010, 03:02:25 PM #8 Last Edit: February 18, 2010, 03:04:26 PM by sapero
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 :)

ckoehn

sapero,

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

Thanks,
Clint

sapero

The latest pak is from 11 july 2009. I have a queued update with the latest DirectX, old directx media, and some bugfixes.