Jump to content

Stacks Library


Recommended Posts

If I undertood correctly, when the app is initiated a hook is created for the WH_CBT message, which got's fired whenever a window is minimized... then the code in the dll's hook uses SendMessage to send a message to VisualTooltip carrying (I guess) the window handle of the window that's being minimized. Finally, this message is processed by VisualToolTip's message loop which takes the handle and uses PrintWindow to create a snapshot out of it?

re there any considerations I should take to create a message hook (I have neved done that before) at least not in windows... oh god, that made me remember my old DOS days!)

Another thing... while reading the MSDN docs I get the impression that the DLL containing the hook's code should be in an independent dll from the application one (in my case the Docklet's dll), so I should use LoadLibrary at DockletCreate to load the docklet dll. The hook dll should only contain the hook procedure? nothing else?

Edited by Smaky
Link to post

About MSDN docs and separate hook code:

The hook code must be in a DLL. This is the reason why they say "separate from application". In this case, "application" is RocketDock, ObjectDock or whatever. Your docklet is already a DLL :) and yes, you can just put the hook function in your DLL instead of writing a separate one just for the hook. There can be other functions in DLL apart from hook function and you can call other functions from there, though I wouldn't call docklet functions/events from hook function. Use IPC techniques instead, such as SendMessage. You can try using SendMessage to hwndDocklet and then use OnProcessMessage, this works at least with RocketDock and ObjectDock, dunno other docks.

Fiuuu this was too large, I should have sent you it in spanish via PM, but at least any other coder reading this will find it useful too.

I'm thinking about using Windows hooks to perform session-wide API hooking (the DLL would intercept API functions at DLLMain (reason = DLL_ATTACH_PROCESS)). Though I'm not convinced about CBT to do this... because I don't know if it fits my future plans:

- PrintWindow cache.

- Intercept TrackPopupMenu[Ex] to show skinned menus a-la Leopard.

- Remove window menu bar and add something like McBar and Rosie do.

- Intercept DefWindowProc for WM_NCPAINT and WM_NCACTIVATE, WM_NCHITTEST etc... and draw buttons to the left and icon to the middle, just like AppleMinMax but without dirty tricks (ok, maybe this is a dirtier trick... depends on your point of view).

- Intercept scrollbar painting to fix track button background (in Leopard track button background remains fixed, doesn't travel with track button, this was requested in some thread at AquaSoft some time ago and I verified in a Mac and it's true it behaves like that).

- Animated... errr... progress bars... :P

Mmm... I think I had more ideas but can't remember them just now. Whatever, don't expect any of these to be implemented in any time soon, I have a lot to study, prepare for exams, polish lot of stuff at work, etc... :(

Link to post

@Smaky: see code of the hook (C++) ( Caller and DLL )

//-----------------------------------------------------------------------------------------------------------------------------
/////// MAIN WINDOW
//-----------------------------------------------------------------------------------------------------------------------------
//DLL Loading and call
typedef LRESULT (WINAPI *ATTACH_FUNCTION_POINTER)(HWND _parent);
typedef LRESULT (WINAPI *DETACH_FUNCTION_POINTER)();

ATTACH_FUNCTION_POINTER pfAttach;
DETACH_FUNCTION_POINTER pfDetach;
HMODULE hInjectDLL = NULL;


hInjectDLL = LoadLibrary(HOOKDLL);
if(hInjectDLL != NULL)
{
pfAttach = (ATTACH_FUNCTION_POINTER)GetProcAddress(hInjectDLL, "InstallHook");
pfDetach = (DETACH_FUNCTION_POINTER)GetProcAddress(hInjectDLL, "UnInstallHook");

if(pfAttach == NULL || pfDetach == NULL )
{
MessageBox("Error in DLL", "Error", MB_OK|MB_ICONERROR);
return;
}

if(pfAttach(m_hWnd) == FALSE)
{
MessageBox("Error install hook","Error",0);
}
}



..../.....


void CVisualToolTipMain::OnDestroy()
{
if (hInjectDLL==TRUE)
{
FreeLibrary(hInjectDLL);
pfDetach();
}

CDialog::OnDestroy();
}




//-----------------------------------------------------------------------------------------------------------------------------
// DLL
//-----------------------------------------------------------------------------------------------------------------------------
// Hooks.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include <stdlib.h>
#include <objbase.h>
#include <Shellapi.h>
#include <commctrl.h>
// constant /////////////////////////////////////////////////////////////////////////
//
#define MYWM_HOOKMINIMIZED (WM_USER+3)
#define MYWM_HOOKQUIT (WM_USER+4)
#define MYWM_HOOKEXCLU (WM_USER+5)


// define share section for all hooked process //////////////////////////////////////
#pragma data_seg(".JOE")
HHOOK g_hCBTHook = NULL;
HWND hwndParent=0;

#pragma data_seg()
#pragma comment(linker, "/section:.JOE,rws")

// global variables /////////////////////////////////////////////////////////////////
//
HINSTANCE ghModule = NULL;

// function prototype ///////////////////////////////////////////////////////////////
//
LRESULT CALLBACK cbtHOOK(int nCode, WPARAM wParam, LPARAM lParam);



BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
// reserve the DLL handle
ghModule = (HINSTANCE)hModule;

//
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}


BOOL WINAPI InstallHook(HWND _parent)
{
hwndParent=_parent;

g_hCBTHook = SetWindowsHookEx(WH_CBT, cbtHOOK, ghModule, 0);
if( g_hCBTHook == NULL )
{
return FALSE;
}

return TRUE;
}


BOOL WINAPI UnInstallHook()
{
// unhook
return UnhookWindowsHookEx(g_hCBTHook);
}


LRESULT CALLBACK cbtHOOK(int nCode, WPARAM wParam, LPARAM lParam)
{
// return immediately if system required
if (nCode < 0)
{
return CallNextHookEx(g_hCBTHook, nCode, wParam, lParam);
}

HWND hwnd;
switch(nCode)
{
case HCBT_DESTROYWND:
PostMessage(hwndParent,MYWM_HOOKQUIT,wParam,0); // to deleted cached screenshot
break;

case HCBT_MINMAX:
hwnd=(HWND)wParam;

if (::IsWindowVisible(hwnd))
{
int command=LOWORD(lParam);
if (command==SW_MINIMIZE||command==SW_FORCEMINIMIZE||command==SW_SHOWMINIMIZED||
command==SW_SHOWMINNOACTIVE)
{
if (SendMessage(hwndParent,MYWM_HOOKEXCLU,(WPARAM)(hwnd),0)==0) // If the minimized window is excluded, don't screenshot
{
SendMessage(hwndParent,MYWM_HOOKMINIMIZED,(WPARAM)(hwnd),0);
}
}
}
break;
}

return CallNextHookEx(g_hCBTHook, nCode, wParam, lParam);
}

Link to post

Thanks ChristianS,

Youe sample clarifies a few things, as I thought you are sending the hWnd to the application via SendMessage where it is processed by its Message loop with a PrintWindow, thanks man!

Additionally I've read a 1996 (or it was 1997) Under the HoodMSJ article from Matt Prietek which states thet the gobal hook will be injected to every process ran, so we should take special care with the dll's footprint in order to mantain it as slim as possible. So it would be advisable in my environment (where I have already a DLL - the docklet's DLL) to have a sepparate DLL for the Hook stuff or should I include it on the docklet's DLL?

Link to post

I dunno about data/bss segments (haven't tested) but at least code and shared segments don't get duplicated, so no resource consumption by that side.

Maybe Windows implements copy-on-write for data/bss segments? (at least Linux and other systems do) in such case dll footprint would be no problem at all, indeed you would get roughly 4 kbyte additional memory consumption for each running process, in theory.

Link to post

Thanks you both, I went with a sepparate HOOK dll... just in case and applied Matt Prietek's advice on reducing the DLL footprint (which, as you mention matonga) is just about 4K.

Right now I am seeing the messages being passed from the Hook, I still need to implement them in my Docklet... but for now I'm leaving on vacation until next monday.

Have a great week! Thank you both again.

Edit:

Opps... sorry for the double post! Thanks

Ok, I have created a TaskListHook.dll which sends messages to the TaskList Docklet whenever an app is being minimized. Giving it the opportunity to create a spnapshot of the app before it is actually minimized. Messages are working just fine!

Matonga, I have one question here, since the images are being updated dynamically (whenever an app is minimized) how should I "tell" stacklibrary of the change. Currently inside MyProviderInit the stack icons are created out of the actual icon images of my (internal dynamic array) task list items (which includes the application icon & scaled snapshot). MyProviderInit is called whenever the stack is shown (and, of course all items are destroyed upon stack hide... which was something I want to optimize).

Is there a way to update the stack items and/or icons without freeing it completely first, thus the need for recreating them?

Edit 2:

I am having problems with the IconToAlphaBitmap function, for some application icons it is not retreiving the actual icon bitmap... further investigation on the issue has shown that

Bitmap::FromHBITMAP(ii.hbmColor, 0);

returns Bitmap object with PixelFormat32bppRGB format... but later during the call to:

Gdiplus::Bitmap *dstBitmap = new Bitmap(bmData.Width, bmData.Height, bmData.Stride, PixelFormat32bppARGB, (BYTE*) (bmData.Scan0));

it is being interpreted as a PixelFormat32bppARGB bitmap.

The problem is that if I use PixelFormat32bppRGB in the previous statement, no icon is lost, but they are created with a black background instead of a transparent one. In fact, the Alpha info is lost (which is expected) but, when using PixelFormat32bppARGB some icons are lost, a completely transparent image is generated. What could be causing this?

Further investingation on this issue showed that the probles lies with applications that do not have a large icon associated to them, for example regedit.exe, if you open this application no icon is retrieved with the original code, but with PixelFormat32bppRGB it shows it's icon.

Edit 3:

With the following code the icon is not lost and the transparent areas are preserved but the alpha channel data seems to be lost since pixels which previously where semi transparent are now opaque (they look black).

Gdiplus::Bitmap *IconToAlphaBitmap(HICON hIcon, UINT size = 0)
{
Gdiplus::Bitmap *pIcon = Gdiplus::Bitmap::FromHICON(hIcon);

Gdiplus::Bitmap *pBitmap = new Gdiplus::Bitmap(pIcon->GetWidth(), pIcon->GetHeight(), PixelFormat32bppARGB);
Gdiplus::Graphics *graphics = Gdiplus::Graphics::FromImage(pBitmap);

graphics->SetInterpolationMode(Gdiplus::InterpolationModeHighQuality);
graphics->SetCompositingQuality(Gdiplus::CompositingQualityHighQuality);
graphics->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
graphics->DrawImage(pIcon, 0, 0, pIcon->GetWidth(), pIcon->GetHeight());

delete graphics;
delete pIcon;

return pBitmap;
}

Edit 4:

Unfortunately, all that code does the very same as just:

Gdiplus::Bitmap *pIcon = Gdiplus::Bitmap::FromHICON(hIcon);
return pIcon;

Edit 5:

Well, after a lot of trial & error and loads of debugging I found that the problem occurs for such applications that do not have a native ARGB icon (like regedit.exe). These apps carry only a 32x32 16 color icon with no alpha channel data at all, just transparent pixels. The problem is that with the original IconToAlphaBitmap there seems to be data at the alpha channel (most of it with values close to cero), but nevertheless between 0-255. So IsAlphaBitmap is being set and the icon is retrieved from the Gdiplus::Bitmap and not from the HICON directly. So, as a workaround while I found a better way to distinguish these icons, I am calculating the weighted alpha value for all pixels in the icon, if I get a value lesser than 0.3 then I assume it is a RBG icon and use FromHICON instead of the Gdiplus Bitmap... this way it seems to work, normal icon have shown (so far with my own testing) to have a weighted alpha value close to 1, and are properly shown unsing the (correct) alpha bits from the icon. Check the current TaskList Docklet to see the result.

Edited by Smaky
Link to post
  • 1 month later...

Hi all,

i'm working on StandaloneStack 2 with the stack library, i have a problem to retrieve the icon of the files.

2 ways :

FIRST :

appObject->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pidlLocal, IID_IExtractIcon, NULL,(void**)&extractIcon);
extractIcon->GetIconLocation(0, iconLocation, MAX_PATH, &iconIndex, &iconFlags);
extractIcon->Extract(iconLocation, iconIndex , &icon, &tmpIcon, MAKELONG(iconSize, 16));
return icon;

Works good but icon quality not perfect.

SECOND :

SHFILEINFO fi;
HIMAGELIST * imagelist;
ZeroMemory(&fi, sizeof(fi));
SHGetFileInfo((LPCWSTR) pidlLocal, -1, &fi, sizeof(fi),SHGFI_SYSICONINDEX|SHGFI_PIDL );
hr=SHGetImageList( isVista?SHIL_JUMBO:SHIL_EXTRALARGE,IID_IImageList,(void**) &imagelist);
if(SUCCEEDED(hr))
{
((IImageList*)imagelist)->GetIcon(fi.iIcon,ILD_IMAGE|ILD_TRANSPARENT,&icon);
((IImageList*)imagelist)->Release();
}
if (icon)
{
extractIcon->Release();
return icon;
}

Works good too, icon quality is very good but it retreive default icon of .exe ( the icon of all executable, not the specific icon of the file) and some icon( pdf from Foxit PDF Reader for example ) is small (but iconinfo says 256x256 pixels !).

So i don't know how to distinguish good quality icon and poor quality icon (and default exe...)

what is the real technic to extract a high resolution icon !?

2 questions for stack library :

- is it possible to dynamically change the images in the stack (openned), i see FanStack_Repaint but it does nothing.

i've tried to change the buffer in STACK_ITEM (*pixels) but it doesn't work, i suppose that the library do a copy of this buffer.

It would be cool if we can change the image when the stack if openned ( for exemple : Grid/FanStack_UpdateImage(int index,void * pixels ) )

- what does special_last_item ? it seems that true of false does the same thing ?

Link to post

Hey guys :)

I'm working at another project, not at XWD. But, for now I know how to extract High Quality Icons. If you want me to publish this code, I can :) it's on delphi 2009.

I just copy from my sources, therefore if you need anything else, just tell me

function GetLargeIconSize(const FileName: String): Integer;

type
TIconDirEntry = packed record
bWidth: Byte;
bHeight: Byte;
bColorCount: Byte;
bReserved: Byte;
wPlanes: Word;
wBitCount: Word;
dwBytesInRes: DWord;
dwImageOffset: DWord;
end;
TArrayIconDirEntry = array[0..0] of TIconDirEntry;
PArrayIconDirEntry = ^TArrayIconDirEntry;

TIconDir = packed record
idReserved: Word; // = 0 ?
idType: Word; // = 1 ?
idCount: Word;
end;

var
f: File;
IconDir: TIconDir;
IconEntries: PArrayIconDirEntry;
i: Integer;
begin
Result := GetSystemMetrics(SM_CXICON);

{$I-}
AssignFile(f, FileName);
Reset(f, 1);

FillChar(IconDir, SizeOf(TIconDir), 0);
BlockRead(f, IconDir, SizeOf(TIconDir));

if (IconDir.idReserved = 0) and (IconDir.idType = 1) then
begin
GetMem(IconEntries, IconDir.idCount * SizeOf(TIconDirEntry));
BlockRead(f, IconEntries^, IconDir.idCount * SizeOf(TIconDirEntry));

for i:= 0 to IconDir.idCount - 1 do
begin
if (Result < IconEntries^[i].bWidth) then
Result := IconEntries^[i].bWidth;
end;

FreeMem(IconEntries);
end;

CloseFile(f);
{$I+}
end;

function GetIconFromFile(FileName: String): HICON;

function IS_INTRESOURCE(const ARes: DWord): Boolean;
begin
Result := ((ARes shr 16) = 0);
end;

type
PEnumData = ^TEnumData;
TEnumData = record
Name: String;
Index: Integer;
Counter: Integer;
end;

function EnumResNameProc(hModule: DWord; lpszType: PWChar; lpszName: PWChar; EnumData: PEnumData): Boolean; stdcall;
begin
if (EnumData^.Counter = EnumData^.Index) then
begin
if IS_INTRESOURCE(DWord(lpszName)) then
EnumData^.Name := Format('#%d', [DWord(lpszName)])
else
EnumData^.Name := lpszName;
Result := False;
end else
begin
Inc(EnumData^.Counter);
Result := True;
end;
end;

var
hModule: DWord;
hResource: DWord;
hMem: DWord;
lpResource: Pointer;
nID: Integer;
EnumData: TEnumData;
Ext: String;
IconSize: Integer;
sfi: TSHFileInfo;
FileType: (ftAnother, ftExecutable, ftIcon);
ImageList: HIMAGELIST;
Flags: DWord;
PIDL: PItemIDList;
begin
Result := 0;

PIDL := SHSimpleIDListFromPath(PWChar(FileName));

if DirectoryExists(FileName) then
begin
FillChar(sfi, SizeOf(TSHFileInfoW), 0);
SHGetFileInfo(PWChar(FileName), 0, sfi, SizeOf(sfi), SHGFI_ICONLOCATION);
if (sfi.szDisplayName[0] <> #0) then
FileName := sfi.szDisplayName;
end else
if Assigned(PIDL) then
begin
FillChar(sfi, SizeOf(TSHFileInfoW), 0);
SHGetFileInfo(PWChar(PIDL), 0, sfi, SizeOf(sfi), SHGFI_ICONLOCATION or SHGFI_PIDL);
if (sfi.szDisplayName[0] <> #0) then
FileName := sfi.szDisplayName;
end;

Ext := ExtractFileExt(FileName);
FileType := ftAnother;

if (CompareStr(Ext, '.exe') = 0) or (CompareStr(Ext, '.ocx') = 0) or
(CompareStr(Ext, '.dll') = 0) or (CompareStr(Ext, '.scr') = 0) or
(CompareStr(Ext, '.bin') = 0) or (CompareStr(Ext, '.cpl') = 0) then
FileType := ftExecutable
else
if (CompareStr(Ext, '.ico') = 0) or (CompareStr(Ext, '.icon') = 0) then
FileType := ftIcon;

case FileType of

ftExecutable:
begin
hModule := LoadLibraryEx(PWChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);

if (hModule > 0) then
begin
if (sfi.iIcon >= 0) then
begin
EnumData.Index := sfi.iIcon;
EnumData.Counter := 0;
EnumResourceNames(hModule, MakeIntResource(3 + DIFFERENCE), @EnumResNameProc, Integer(@EnumData));
end else
EnumData.Name := Format('#%d', [-sfi.iIcon]);

hResource := FindResource(hModule, PWChar(EnumData.Name), MakeIntResource(3 + DIFFERENCE));

if (hResource > 0) then
begin
hMem := LoadResource(hModule, hResource);
lpResource := LockResource(hMem);

if Assigned(lpResource) then
begin
nID := LookupIconIdFromDirectoryEx(lpResource, True, $200, $200, LR_DEFAULTCOLOR);
hResource := FindResource(hModule, MakeIntResource(nID), MakeIntResource(3));

if (hResource > 0) then
begin
hMem := LoadResource(hModule, hResource);
lpResource := LockResource(hMem);

if Assigned(lpResource) then
Result := CreateIconFromResourceEx(lpResource, SizeofResource(hModule, hResource),
True, $00030000, 0, 0, LR_DEFAULTCOLOR);
end;
end;
end;

FreeLibrary(hModule);
end;
end;

ftIcon:
begin
IconSize := GetLargeIconSize(FileName);
Result := LoadImage(0, PWChar(FileName), IMAGE_ICON, IconSize, IconSize, LR_LOADFROMFILE or LR_COLOR);
end;

end;

if (Result = 0) and Assigned(PIDL) then
begin
SHGetFileInfo(PWChar(PIDL), 0, sfi, SizeOf(sfi), SHGFI_TYPENAME or SHGFI_PIDL);

Flags := SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_PIDL;
if (sfi.szTypeName = 'Shortcut') then
Flags := Flags or SHGFI_LINKOVERLAY;

ImageList := SHGetFileInfo(PWChar(PIDL), SFGAO_SHARE, sfi, SizeOf(sfi), Flags);
if (ImageList > 0) then
Result := ImageList_GetIcon(ImageList, sfi.iIcon, ILD_NORMAL);
end;

if Assigned(PIDL) then
FreePIDL(PIDL);
end;

And TDIB - it's my class for working with HBITMAP + HDC + Gdiplus::GpBitmap (not Gdiplus::Bitmap)

I hope you will understand

procedure GetBitmapFromIcon(Icon: HICON; DIB: TDIB);
var
ii: TIconInfo;
maskDC, mainDC: HDC;
maskOld, mainOld: HBITMAP;
BitmapData: BITMAP;
p: PARGB;
i: Integer;
Check: Boolean;
begin
GetIconInfo(Icon, ii);

GetObject(ii.hbmColor, SizeOf(BITMAP), @BitmapData);

mainDC := CreateCompatibleDC(0);
maskDC := CreateCompatibleDC(0);
maskOld := SelectObject(maskDC, ii.hbmMask);
mainOld := SelectObject(mainDC, ii.hbmColor);

DIB.Resize(BitmapData.bmWidth, BitmapData.bmHeight);

if (BitmapData.bmBitsPixel < 32) then
begin
BitBlt(DIB.DC, 0, 0, BitmapData.bmWidth, BitmapData.bmHeight, maskDC, 0, 0, SRCCOPY);
BitBlt(DIB.DC, 0, 0, BitmapData.bmWidth, BitmapData.bmHeight, maskDC, 0, 0, DSTINVERT);
BitBlt(DIB.DC, 0, 0, BitmapData.bmWidth, BitmapData.bmHeight, mainDC, 0, 0, SRCAND);
end else
begin
BitBlt(DIB.DC, 0, 0, BitmapData.bmWidth, BitmapData.bmHeight, mainDC, 0, 0, SRCCOPY);
end;

// Check old icons >> 32 bits
Check := True;
p := DIB.Bits;
for i:= 0 to DIB.Width * DIB.Height - 1 do
begin
if (p^.a > 0) then
begin
Check := False;
Break;
end;
inc(p);
end;

if Check then
begin
p := DIB.Bits;
for i:= 0 to DIB.Width * DIB.Height - 1 do
begin
if (p^.c > 0) and (p^.a = 0) then
p^.a := 255;
inc(p);
end;
end;

SelectObject(maskDC, maskOld);
SelectObject(mainDC, mainOld);
DeleteDC(maskDC);
DeleteDC(mainDC);
DeleteObject(ii.hbmMask);
DeleteObject(ii.hbmColor);
end;

Link to post
  • 2 months later...

Hi guys.

I need some help with hooks. In XP it is okay, as usual ;) but seven and vista... anyway, when I installed a hook HCBT to intercept minimization of windows, I do this

case HCBT_MINMAX:
{
HWND wnd = /*some window*/;
if(IsWindow((HWND)wParam) && wnd)
{
switch(LOWORD(lParam))
{
case SW_MINIMIZE:
case SW_SHOWMINIMIZED:
case SW_FORCEMINIMIZE:
case SW_SHOWMINNOACTIVE:
{
SendMessage(wnd, xxx, wParam, xxx);
}
break;

So, a lot of windows (for example explorer's windows) minimize through this hook, but when I try to minimize IE it seems that it doesn't go trhough this hook. Any solutions ? RocketDock minimize IE well, as addition.

Thanks.

Link to post

I'm doing something like this on my TaskList Docklet (altough it is not yet compatible with W7 it works almost fine on vista):

	case HCBT_MINMAX:
if (::IsWindowVisible((HWND)wParam))
{
int command = LOWORD(lParam);
if (command == SW_MINIMIZE||command==SW_FORCEMINIMIZE||command==SW_SHOWMINIMIZED|| command==SW_SHOWMINNOACTIVE)
{
if (SendMessage(hwndParent, MYWM_HOOKEXCLU, wParam,0) == 0) // If the minimized window is excluded, don't screenshot
{
SendMessage(hwndParent, MYWM_HOOKMINIMIZED, wParam, 0);
}
}
}
break;

I have not noticed that IE is not being handled by the hook, but I have noticed some erratic behaviour with FireFox (as if it minimize/restore) multiple times.

Link to post

I've decompiled RocketDock.dll :) but I can't understand the whole picture of WindowProc asm code.

I just wonder, at first in the Window Proc RocketDock do this

1. Find ROCKETDOCK window

2. Check if the minimized window is visible and not iconic

3. Call OpenProcess to get BaseName of application's window

4. Then try to get properties of Rocketdock's window "FILTER", may be it checks if window can be minimized into the dock.

5. PostMessage to let the dock about minimizing window.

I just can't understand why they use GetAsyncKeyState in the hook, and I can not find a "swtich()" section, where thet check if it is HCBT_MINMAX and then minimize it.

Thanks.

Edit:

Okay, I think found it:

mov	 eax, [esp+4E8h+nCode]
sub eax, 1 // 1 - it is HCBT_MINMAX
mov esi, [esp+4E8h+uMsg]
jz short loc_10001B05

But it seems that this hook doesn't work for IE (may be some other apps). May be I should install hook or load library using another way, or may be some aspects which I should know about, because it works perfect in Xp.

Link to post
  • 1 month later...
This is just a weird proposal, but...

Lot's of apps do screenshots... WinExposé, Devrextster's dExpose, Smaky's Task Docklet, TaskSwitch XP, etc...

I'm serioulsy considering to write a PrintWindow API hihack to allow for window cache. It would look something like this:

PrintWindowCache.png

<edit>in picture, where it says "original PW api" it refers to interaction between pw cache app and currently running applications.</edit>

Explanation of the Java/GTK stuff: I've experimented with Pidgin/other GTK apps, and Java apps a lot of time ago (now I use Digsby instead of Pidgin) and found you can just set them to layered (SetWindowLong (gtkappwindow, ... Or WS_EX_LAYERED) then SetLayeredWindowAttributes (blablabla, alpha = 0xFF, ...)) and it happens you can then just use GetWindowDC and BitBlt instead of PrintWindow, and you get the window contents instead of just a black window. However you can't use this technique with other apps such as DirectX accelerated apps, Windows Media Player flickers and freezes, and other problems. Of course this is a Windows XP specific topic, for Vista and 7 just use the DWM API instead. :P

Hey Matonga.

Are you still thinking/working on it ? I just want to develop it, or connect to you to help and continue working on this library.

What do you think?

Edit

May be, we can modify StackLib to make it faster and liked Snow Leopard's one. What do you think? I just do not want to begin coding it from the begining.

Link to post
  • 4 weeks later...
  • 11 months later...

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...