News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

CWndShadow

Started by hfheatherfox07, October 06, 2011, 07:29:23 PM

Previous topic - Next topic

hfheatherfox07

Do we have some thing similar to this in MASM?

http://www.codeproject.com/KB/dialog/FrameShadow.aspx


hfheatherfox07

What is the proper API command to create a shadow?

baltoro

#2
I'm curious,...did you read the source code: WndShadow.cpp ??? He calls LoadLibrary, and, then,...UpdateLayeredWindow function.
I think, if you want to do something like that, it would be more difficult in a Pre-Vista operating System. You could paint a graphic shadow fairly simply over the Desktop Window, but, if your Window overlaps a window from another application, it's gonna be a major pain-in-the-ass.
Baltoro

hfheatherfox07

#3

hfheatherfox07

#4
UpdateLayeredWindow function is used but it is not the function that creats the shadows ....

Also it is window 2000 and XP .... not  Pre-Vista operating System

hfheatherfox07

Well ...Looking through the WndShadowDemo ( the simple window ) NoneMFCDemo.cpp is fairly familar I think I can translate that ....
It looks like on line 39 CWndShadow::Initialize(hInstance); <- how do you translate that to MASM?
and than line 177 case WM_CREATE:
// Create the shadow
WndShadow.Create(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}


that is were the function "WndShadow" is invoked which is in the WndShadow.h wich I assume is like an include for us .... Can't translate that.... :(


baltoro

The C++ code you are referring to (from WndShadow.cpp):

bool CWndShadow::Initialize(HINSTANCE hInstance)
{
// Should not initiate more than once
if (NULL != s_UpdateLayeredWindow)
return false;

HMODULE hSysDll = LoadLibrary(_T("USER32.DLL"));
s_UpdateLayeredWindow =
(pfnUpdateLayeredWindow)GetProcAddress(hSysDll,
"UpdateLayeredWindow");

// If the import did not succeed, probably layered window is not supported by current OS
if (NULL == s_UpdateLayeredWindow)
return false;

hSysDll = LoadLibrary(_T("dwmapi.dll"));
if(hSysDll) // Loaded dwmapi.dll succefull, must on Vista or above
{
s_bVista = true;
s_DwmIsCompositionEnabled =
(pfnDwmIsCompositionEnabled)GetProcAddress(hSysDll,
"DwmIsCompositionEnabled");
}

// Store the instance handle
s_hInstance = hInstance;

// Register window class for shadow window
WNDCLASSEX wcex;

memset(&wcex, 0, sizeof(wcex));

wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = DefWindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = strWndClassName;
wcex.hIconSm = NULL;

RegisterClassEx(&wcex);

return true;
}


...This seems pretty simple to translate into MASM assembly. It does three things:

  • Checks to see if the CWndShadow object has already beem initialized.
  • Calls LoadLibrary, and then GetProcAddress to see if UpdateLayeredWindow exists on the local machine
  • Registers the CWndShadow Window class

The only real difficulty is that there are no classes in assembly language,...and, you will have to create a data structure that is equivalent to the class.
Baltoro

baltoro

I don't know if you are familiar with the syntax of C++, but, here is the definition of the CWndShadow class (from: WndShadow.h -- the header file, which is similar to an include file in assembly):

class CWndShadow
{
public:
CWndShadow(void);
public:
virtual ~CWndShadow(void);

protected:

// Instance handle, used to register window class and create window
static HINSTANCE s_hInstance;

#pragma warning(push)
#pragma warning(disable:4786)
// Parent HWND and CWndShadow object pares, in order to find CWndShadow in ParentProc()
static std::map<HWND, CWndShadow *> s_Shadowmap;
#pragma warning(pop)

// Layered window APIs
typedef BOOL (WINAPI *pfnUpdateLayeredWindow)(HWND hWnd, HDC hdcDst, POINT *pptDst,
SIZE *psize, HDC hdcSrc, POINT *pptSrc, COLORREF crKey,
BLENDFUNCTION *pblend, DWORD dwFlags);
static pfnUpdateLayeredWindow s_UpdateLayeredWindow;

// Vista compatibility APIs
static bool s_bVista; // Whether running on Win Vista
typedef HRESULT (WINAPI *pfnDwmIsCompositionEnabled)(BOOL *pfEnabled);
static pfnDwmIsCompositionEnabled s_DwmIsCompositionEnabled;

HWND m_hWnd;

LONG m_OriParentProc; // Original WndProc of parent window

enum ShadowStatus
{
SS_ENABLED = 1, // Shadow is enabled, if not, the following one is always false
SS_VISABLE = 1 << 1, // Shadow window is visible
SS_PARENTVISIBLE = 1<< 2, // Parent window is visible, if not, the above one is always false
SS_DISABLEDBYAERO = 1 << 3 // Shadow is enabled, but do not show because areo is enabled
};
BYTE m_Status;

unsigned char m_nDarkness; // Darkness, transparency of blurred area
unsigned char m_nSharpness; // Sharpness, width of blurred border of shadow window
signed char m_nSize; // Shadow window size, relative to parent window size

// The X and Y offsets of shadow window,
// relative to the parent window, at center of both windows (not top-left corner), signed
signed char m_nxOffset;
signed char m_nyOffset;

// Restore last parent window size, used to determine the update strategy when parent window is resized
LPARAM m_WndSize;

// Set this to true if the shadow should not be update until next WM_PAINT is received
bool m_bUpdate;

COLORREF m_Color; // Color of shadow

public:
static bool Initialize(HINSTANCE hInstance);
void Create(HWND hParentWnd);

bool SetSize(int NewSize = 0);
bool SetSharpness(unsigned int NewSharpness = 5);
bool SetDarkness(unsigned int NewDarkness = 200);
bool SetPosition(int NewXOffset = 5, int NewYOffset = 5);
bool SetColor(COLORREF NewColor = 0);

protected:
//static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK ParentProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

// Redraw, resize and move the shadow
// called when window resized or shadow properties changed, but not only moved without resizing
void Update(HWND hParent);

// Fill in the shadow window alpha blend bitmap with shadow image pixels
void MakeShadow(UINT32 *pShadBits, HWND hParent, RECT *rcParent);

// Helper to calculate the alpha-premultiled value for a pixel
inline DWORD PreMultiply(COLORREF cl, unsigned char nAlpha)
{
// It's strange that the byte order of RGB in 32b BMP is reverse to in COLORREF
return (GetRValue(cl) * (DWORD)nAlpha / 255) << 16 |
(GetGValue(cl) * (DWORD)nAlpha / 255) << 8 |
(GetBValue(cl) * (DWORD)nAlpha / 255);
}

// Show or hide the shadow, depending on the enabled status stored in m_Status
void Show(HWND hParent);
};


It's alot more complicated than is necessary, and converting that to a useful data structure in MASM assembly language is going to take some thought.   
In C++, a class usually includes what are called member variables (in MASM, these would just be known as data variables, which you should initialize to reasonable default values), and, a number of function prototypes (which in MASM, you would just refer to as routines). Unfortunately, in the above class definition, the author just mixes these up in his listing (which is legal, but difficult to read for novices).

The first two function prototypes in the listing:   

public:
CWndShadow(void);
public:
virtual ~CWndShadow(void);


...are known as the class constructor and the class destructor,...and, there are no equivalents in MASM assembly language. However, you should write a routine that sets your data to default values (this is what a class constructor does in C++). When an instance of the class is instantiated in C++ (created, syntactically), the class constructor is automatically invoked. In MASM assembly, you would just write this routine, and use the INVOKE syntax in your code when you wanted to first create your Shadowd Window (doing this in the Initialize routine would be appropriate). The class desstructor in C++ usually just deletes any memory allocations and system resources that were made for the CWndShadow object (if it is a simple class like this one, it does nothing and just returns TRUE).
Baltoro

hfheatherfox07

I found this:
(~249kb) C to ASM Compiler (c) 2003 by Muhammad Owais Khan Afridi
    Minimalistic C-like compiler created by some Pakistani student as his project on a compiler construction course. The outputted code is non optimized greatly. Some examples and a detailed description of intrinsic routines are included. One remark: use MSVC++ 6.0 only to recompile (since Watcom and Mingw did not succeed).
    Source text: .cpp (MS Visual C++ 6.0 only)
    Output language: .asm (16-bit => Tasm, Masm => mz .exe)
    Documentation: in English



hfheatherfox07


dedndave

that's some old stuff - looks like 16-bit


dedndave

that is transparency - not a shadow
and the attachment has 2 nice examples in it

hfheatherfox07

Well on my computer I see a shadow ?.....

Can any body tell me what the ASM's in here do ? http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=42918&lngWId=1

That is the source code for shadows it is in VB + ASM .... but I don't understand were the author is going with this


Thank you


hfheatherfox07

Quote from: dedndave on October 09, 2011, 01:27:28 AM
that is transparency - not a shadow
and the attachment has 2 nice examples in it


Here is a variation of that ( not mine ) from here :  http://bbs.pediy.com/archive/index.php?t-23389.html

Attachment :
http://www.masm32.com/board/index.php?PHPSESSID=e7352f0e4c241548b294eb88f8214ed1&action=dlattach;topic=769.0;id=396

use the transparent .png from the above attachment and rename it to "ScrollText.png"


make an rsrc.rc and add 1 RCDATA DISCARDABLE "ScrollText.png"

you will see the scrolling  transparent .png..... Sooo Cool  :U
Don't forget that you must use a .png with a transparent backgroung in order for this to work  :bg
;====================================
.586
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
include \masm32\include\pnglib.inc

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\pnglib.lib

include \masm32\macros\macros.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Constants & struct missing from Windows.inc
WS_EX_LAYERED equ 80000h
ULW_COLORKEY equ 1h
ULW_ALPHA equ 2h
ULW_OPAQUE equ 4h
AC_SRC_OVER equ 0h
AC_SRC_ALPHA equ 1h
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
BLENDFUNCTION STRUCT
BlendOp BYTE ?
BlendFlags BYTE ?
SourceConstantAlpha BYTE ?
AlphaFormat BYTE ?
BLENDFUNCTION ends
;------------------------------------
sSIZE STRUCT
dWidth DWORD ?
dHeight DWORD ?
sSIZE ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
ClassName db "MainWinClass",0
AppName db "Main Window",0
ptZero POINT <0,0>
blender BLENDFUNCTION <AC_SRC_OVER,0,255,AC_SRC_ALPHA>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hTimer dd ?
hInstance HINSTANCE ?
hWin dd ?
CommandLine LPSTR ?
pUlw dd ?
hScreenDC dd ?
hBitmap dd ?
hBitmap2 dd ?
hMemDC dd ?
hMemDC2 dd ?
hOldBmp dd ?
hOldBmp2 dd ?
pngSize sSIZE <>
winSize sSIZE <>
winY dd ?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
CenterScreen PROC USES esi edi _hWnd:DWORD
LOCAL wRect:RECT

xor eax, eax
push eax
lea eax, DWORD PTR [ebp-16]
push eax
mov eax, _hWnd
push eax
call GetWindowRect ;MROM Penalty
mov esi, wRect.bottom
sub esi, wRect.top
push esi
shr esi, 1
mov edi, wRect.right
sub edi, wRect.left
push edi
shr edi, 1
mov eax, SM_CYSCREEN
push eax
call GetSystemMetrics ;MROM Penalty
shr eax, 1
sub eax, esi
push eax
mov eax, SM_CXSCREEN
push eax
call GetSystemMetrics ;MROM Penalty
shr eax, 1
sub eax, edi
push eax
mov eax, _hWnd
push eax
call MoveWindow ;MROM Penalty
ret

CenterScreen ENDP
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; This code is largely ripped from loadfromresource example in PngLib
LoadPng proc ID:dword,pSize:dword

; In: ID: Resource ID of PNG file to load
; Out: pSize: Struct that this points to is filled with width & height of PNG
; eax Contains the handle to the new DIB

LOCAL pngInfo:PNGINFO

; --- Initialize structure ---
invoke PNG_Init, addr pngInfo

; --- Load PNG resource ---
invoke PNG_LoadResource, addr pngInfo, hInstance, ID
.IF !eax
xor eax, eax
jmp @cleanup
.ENDIF

; --- Decode PNG data ---
invoke PNG_Decode, addr pngInfo
.IF !eax
xor eax, eax
jmp @cleanup
.ENDIF

; --- Create bitmap from PNG ---
invoke PNG_CreateBitmap, addr pngInfo, hWin, PNG_OUTF_AUTO, FALSE
.IF !eax
xor eax, eax
jmp @cleanup
.ENDIF

mov edi,pSize
.if edi!=0
lea esi,pngInfo
movsd
movsd
.endif

@cleanup:
push eax

; --- Cleanup ---
invoke PNG_Cleanup, addr pngInfo

pop eax
ret ; Returns 0 if something went wrong, else bitmap handle

LoadPng endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
FadeBitmap proc hBmp:dword

LOCAL bminfo:BITMAP

invoke GetObject,hBmp,sizeof bminfo,addr bminfo
cmp bminfo.bmBitsPixel,32
jne Abort
mov esi,bminfo.bmBits
yloop:
mov ecx,bminfo.bmWidth
; Set up the alpha for this scanline (in bl). Will be blended 50% with image alpha.
mov ebx,bminfo.bmHeight
shl bl,1
jnc xloop
not ebx
xloop:
mov eax,[esi]
rol eax,8
mov edx,eax
and eax,0FFh
mul bl
xchg eax,edx
rol eax,8
mul dh ; B * A
rol eax,8
mul dh ; G * A
rol eax,8
mul dh ; R * A
mov al,dh
ror eax,8
mov [esi],eax
add esi,4
dec ecx
jnz xloop
dec bminfo.bmHeight
jnz yloop
Abort:
ret

FadeBitmap endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; This snippet from Eoin's GUIBackBufferShell2 example
CreateCanvas Proc hDC:dword,biWidth:dword,biHeight:dword
LOCAL bih:BITMAPINFOHEADER
LOCAL pBb:dword

lea edx, bih
mov (BITMAPINFOHEADER ptr [edx]).biSize, sizeof(BITMAPINFOHEADER)
mov eax, biWidth
mov (BITMAPINFOHEADER ptr [edx]).biWidth, eax
mov eax, biHeight
mov (BITMAPINFOHEADER ptr [edx]).biHeight, eax
mov (BITMAPINFOHEADER ptr [edx]).biPlanes, 1
mov (BITMAPINFOHEADER ptr [edx]).biBitCount, 32
mov (BITMAPINFOHEADER ptr [edx]).biCompression, BI_RGB
mov (BITMAPINFOHEADER ptr [edx]).biSizeImage, 0
mov (BITMAPINFOHEADER ptr [edx]).biXPelsPerMeter, 0
mov (BITMAPINFOHEADER ptr [edx]).biYPelsPerMeter, 0
mov (BITMAPINFOHEADER ptr [edx]).biClrUsed, 0
mov (BITMAPINFOHEADER ptr [edx]).biClrImportant, 0

invoke CreateDIBSection, hDC, edx, DIB_RGB_COLORS, addr pBb, 0, 0
ret

CreateCanvas EndP
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE
; Load the Png file from the resource
invoke LoadPng,1,addr pngSize
mov hBitmap,eax
push pngSize.dWidth
pop winSize.dWidth
mov winSize.dHeight,255
; Get a screen DC, since UpdateLayeredWindow wants one.
invoke GetDC,0
mov hScreenDC,eax
; Create a new DC to select our bitmap into, since UpdateLayeredWindow doesn't accept
; bare bitmaps.
invoke CreateCompatibleDC,hScreenDC
mov hMemDC,eax
invoke SelectObject,eax,hBitmap
mov hOldBmp,eax
invoke CreateCompatibleDC,hScreenDC
mov hMemDC2,eax
invoke CreateCanvas,hMemDC2,pngSize.dWidth,255
mov hBitmap2,eax
invoke SelectObject,hMemDC2,hBitmap2
mov hOldBmp2,eax

invoke GetModuleHandle,SADD("User32")
invoke GetProcAddress,eax,SADD("UpdateLayeredWindow")
.if eax==NULL
invoke MessageBox,hWnd,SADD("Couldn't find UpdateLayeredWindow API. You need Windows XP or 2000 to run this program."),0,MB_OK
invoke SendMessage,hWnd,WM_CLOSE,0,0
.endif
mov pUlw,eax

mov winY,0
invoke SetTimer,hWnd,1,30,0
mov hTimer,eax
invoke CenterScreen,hWnd

.elseif uMsg==WM_TIMER
invoke BitBlt,hMemDC2,0,0,pngSize.dWidth,255,hMemDC,0,winY,SRCCOPY
inc winY
mov eax,pngSize.dHeight
sub eax,255
.if winY>eax
add eax,255
.if winY==eax
mov winY,0
.else
sub eax,winY
invoke BitBlt,hMemDC2,0,eax,pngSize.dWidth,255,hMemDC,0,0,SRCCOPY
.endif
.endif

invoke FadeBitmap,hBitmap2

push ULW_ALPHA
push offset blender
push 0
push offset ptZero
push hMemDC2
push offset winSize
push NULL
push hScreenDC
push hWnd
mov eax,pUlw
call eax

.ELSEIF uMsg==WM_DESTROY
invoke KillTimer,hWnd,hTimer
; Free window image buffer
invoke SelectObject,hMemDC2,hOldBmp2
invoke DeleteObject,hBitmap2
invoke DeleteDC,hMemDC2
; Free PNG image buffer
invoke SelectObject,hMemDC,hOldBmp
invoke DeleteObject,hBitmap
invoke DeleteDC,hMemDC
; Release our handle to the screen DC
invoke ReleaseDC,hWnd,hScreenDC
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
.ELSEIF uMsg==WM_LBUTTONDOWN
; Move the window when holding down left mouse button
invoke SendMessage,hWnd,WM_NCLBUTTONDOWN,HTCAPTION,lParam
.ELSEIF uMsg==WM_RBUTTONUP
; Close the window when clicking right mouse button
invoke PostMessage,hWnd,WM_CLOSE,0,0
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF

xor eax,eax
ret
WndProc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Standard WinMain, except for WS_EX_LAYERED and WS_POPUP in the CreateWindowEx line.
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG

mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName

invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax

invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax

invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,WS_EX_LAYERED,ADDR ClassName,ADDR AppName,\
WS_POPUP,CW_USEDEFAULT,\
CW_USEDEFAULT,100,100,NULL,NULL,\
hInst,NULL
mov hWin,eax

invoke ShowWindow, hWin,SW_SHOWNORMAL
invoke UpdateWindow, hWin

.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW

mov eax,msg.wParam
ret
WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle, NULL
mov hInstance,eax

invoke GetCommandLine
mov CommandLine,eax

invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

end start

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
rc:
1 RCDATA DISCARDABLE "ScrollText.png"