Aqua-Soft Forums: Stacks Library - Aqua-Soft Forums

Jump to content

  • 3 Pages +
  • 1
  • 2
  • 3
  • You cannot start a new topic
  • You cannot reply to this topic

Stacks Library Rate Topic: ***** 1 Votes

#21 User is offline   Smaky Icon

  • Group: Member
  • Posts: 585
  • Joined: 19-April 08

Posted 05 April 2009 - 03:26 AM

I think a thread for the TaskLisk Docklet (+ Stackslib)... or maybe TaskStacks Docklet is worth... I just wanted to have some developer feedback before posting a preview:

1. Taking snapshots of minimized apps takes time (I have tested it and it might take up to four seconds to get the task list if many windows are minimized.
2. Taking snapshots of only the normal windows (shown) is much faster (since it would not require to do all the transparent-show-minimize stuff needed to generate the snapshot) but it yields those windows without a nice icon... I could use a generic icon combined with the large app icon for those.
3. As in snapshot 2, the hi-res vista icon looks great to... problem is that I have not found a reliable way to retrieve the proper icon.
0

#22 User is offline   matonga Icon

  • Group: Developers
  • Posts: 1,286
  • Joined: 04-September 06

Posted 06 April 2009 - 01:27 AM

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:

Posted Image

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

#23 User is offline   ChristianS Icon

  • Group: Member
  • Posts: 56
  • Joined: 23-January 08

Posted 06 April 2009 - 08:23 AM

Good idea,

for visual tooltip, i do a windows hook to cache minimized screenshot :

SetWindowsHookEx : WH_CBT
-> if code=HCBT_MINMAX (before windows is minimized)
and LOWORD(lParam)==SW_MINIMIZE or SW_FORCEMINIMIZE or SW_SHOWMINIMIZED or SW_SHOWMINNOACTIVE)
-> do the screenshot with printwindow and cache it.

test code=HCBT_MOVESIZE to intercept resizing and update the cache.
0

#24 User is offline   Smaky Icon

  • Group: Member
  • Posts: 585
  • Joined: 19-April 08

Posted 07 April 2009 - 12:04 AM

Interesting... just one question:

When you hook into the WH_CBT message, how do you do the actual "cache" of the bitmap. Is the image saved to a location where Visual Tooltip takes it? Is it sent via a intra-process read/write operation?

Thansk.

View PostChristianS, on Apr 6th 2009, 03:23 AM, said:

Good idea,

for visual tooltip, i do a windows hook to cache minimized screenshot :

SetWindowsHookEx : WH_CBT
-> if code=HCBT_MINMAX (before windows is minimized)
and LOWORD(lParam)==SW_MINIMIZE or SW_FORCEMINIMIZE or SW_SHOWMINIMIZED or SW_SHOWMINNOACTIVE)
-> do the screenshot with printwindow and cache it.

test code=HCBT_MOVESIZE to intercept resizing and update the cache.

0

#25 User is offline   ChristianS Icon

  • Group: Member
  • Posts: 56
  • Joined: 23-January 08

Posted 07 April 2009 - 08:46 AM

yes, in fact, the hook is in a dll which send a message to visual tooltip (a sendmessage to block the hook), then visual tooltip do a printwindow and save the bitmap in its memory.
0

#26 User is offline   Smaky Icon

  • Group: Member
  • Posts: 585
  • Joined: 19-April 08

Posted 07 April 2009 - 09:03 PM

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?

This post has been edited by Smaky: 07 April 2009 - 09:21 PM

0

#27 User is offline   matonga Icon

  • Group: Developers
  • Posts: 1,286
  • Joined: 04-September 06

Posted 08 April 2009 - 03:21 AM

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... :(
0

#28 User is offline   ChristianS Icon

  • Group: Member
  • Posts: 56
  • Joined: 23-January 08

Posted 08 April 2009 - 07:53 AM

@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); 
}

0

#29 User is offline   Smaky Icon

  • Group: Member
  • Posts: 585
  • Joined: 19-April 08

Posted 08 April 2009 - 06:10 PM

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?
0

#30 User is offline   matonga Icon

  • Group: Developers
  • Posts: 1,286
  • Joined: 04-September 06

Posted 08 April 2009 - 06:25 PM

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

#31 User is offline   Smaky Icon

  • Group: Member
  • Posts: 585
  • Joined: 19-April 08

Posted 08 April 2009 - 09:32 PM

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.

This post has been edited by Smaky: 17 April 2009 - 10:17 PM

0

#32 User is offline   Smaky Icon

  • Group: Member
  • Posts: 585
  • Joined: 19-April 08

Posted 14 May 2009 - 02:32 PM

Any news on updates to the library?
0

#33 User is offline   ChristianS Icon

  • Group: Member
  • Posts: 56
  • Joined: 23-January 08

Posted 21 May 2009 - 12:25 PM

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 ?
0

#34 User is offline   BOBAH13 Icon

  • Group: Developers
  • Posts: 462
  • Joined: 06-September 08

Posted 23 May 2009 - 06:57 PM

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;

0

#35 User is offline   BOBAH13 Icon

  • Group: Developers
  • Posts: 462
  • Joined: 06-September 08

Posted 27 May 2009 - 11:56 AM

Hey Matonga.
I think over your stack library. If you want I can help you with this project. For example make possible to make it like The Snow Leopard's one, when you go through directory.
0

#36 User is offline   Smaky Icon

  • Group: Member
  • Posts: 585
  • Joined: 19-April 08

Posted 27 May 2009 - 03:15 PM

Matonga,

If of any help... count with me too.
0

#37 User is offline   BOBAH13 Icon

  • Group: Developers
  • Posts: 462
  • Joined: 06-September 08

Posted 01 August 2009 - 08:22 AM

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

#38 User is offline   Smaky Icon

  • Group: Member
  • Posts: 585
  • Joined: 19-April 08

Posted 03 August 2009 - 12:33 AM

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

#39 User is offline   BOBAH13 Icon

  • Group: Developers
  • Posts: 462
  • Joined: 06-September 08

Posted 03 August 2009 - 04:31 AM

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

#40 User is offline   BOBAH13 Icon

  • Group: Developers
  • Posts: 462
  • Joined: 06-September 08

Posted 23 September 2009 - 08:21 PM

View Postmatonga, on Apr 6th 2009, 02:27 AM, said:

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:

Posted Image

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

  • 3 Pages +
  • 1
  • 2
  • 3
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users