Jump to content

Stacks Library


Recommended Posts

Edit

http://www.matiasmoreno.com.ar/box/StackLib-prebeta-5.rar

StackLib-prebeta-5.rar (@File2Go)

StackLib-prebeta-4.rar (@File2Go)

http://www.matiasmoreno.com.ar/StackLib-prebeta-3.rar

This one comes with:

* Some suggestions from Smaky in the .h file.

* New settings structure for compatibility with future .dll versions.

* Fan.

* Grid.

* An attempt to make .h and .lib files for C/C++ developers (untested).

aquasoft-separator.png

OMG it's 4 a.m.! And I'm supposed to get up at 6 a.m. to go to work.

Ok... this will be fast:

http://www.matiasmoreno.com.ar/StackLib-prebeta-2.rar

It is complete with fan and grid modes, and a Demo project for Delphi.

If anyone feels free to do a port of unitStackLib.pas to C/C++ please contact me.

aquasoft-separator.png

I publish this into Developer's Hangout, as it is intended for developers.

I'm about to publish a pre-beta version of the stacks library.

Do you remember Stacks Docklet? I'm rewriting it from scratch. Part of this process includes writing first a .dll for any coder to use (as long as for private use or with my authorization) (you'll probably be authorized is your app/docklet/widget/whatever is freeware or similar).

I'll be publishing it this night, because I have some important stuff to do now.

The pre-beta version of the library I'm about to publish will have support only for Fan mode, popping upwards (Grid mode and other stuff to come later).

Here is a preview without examples yet:

http://www.matiasmoreno.com.ar/StackLib-prebeta-1.rar

It doesn't have a .h and (.def? .lib? .a?) files for C coders yet, tough I'll eventually add it, with an example too.

Also it is missing some functionality I want to add yet.

aquasoft-separator.png

Edit

I'm almost done with the library.

I can't finish it just now because I'm rushing to a friend's birthday.

I'll publish the library later this night or tomorrow.

Link to post
Pardon my ignorance dude, but is this meant as a docklet for docks just like the Stacks Docklet, or...?

It is meant for developers, to use it in their own applications.

I've completely stopped development of Stacks Docklet, and I've recently begun to write Stacks Docklet 2.0 based on this library. ;)

Link to post
  • 1 month later...

Thanks for upgrading the sdk, i'm working on it for StandaloneStack...

the .h is good.

i don't use the .lib , i do a dynamic call.

A request for the futur:

in the structure ( fan_settings, grid_settings,....) add a field BYTE reserved[1000] at the end.

So, when you add some fields in the next version (like in beta4), you do it at the end ( and change the size reserved[1000] to reserved[996] for ex. ) then the next dll will be compatible with the caller without recompile ( as i do a dynamic call of the dll, i could upgrade to the next version without recompile )

of course you need to manage default value of the fields because all the bytes of reserved will be set to 0, so you will have 0 in the new field ( if the caller use an old version of the structure ).

And if you have a code sample for using IShellFolder... :rolleyes:

Good job !

Edited by ChristianS
Link to post

Ok, so...

Code sample for using IShellFolder... I used VFolder something or etc... from Delphi "Cool Demos" folder... or something else (my job peer is testing an alarm and I can't think with all this noise hahaha).

I'll find it at home... anyway the demo was recommended to me by someone else in this same forum... can't remember where and... f...ck...ng alarm noise, ok I promise I'll write you here when back home.

BTW I wont add a 1000 reserved byte array, there is a better way: a size member at the beginning of the structure ;) (like windows.h cbSize ones) so you just would need this instead (for example):

fan_settings_t settings;
bzero (&settings, sizeof(settings));
settings.size = sizeof(settings);
...

Delphi coders:

var
settings: TFanSettings;
begin
FillChar (settings, sizeof(settings), 0);
settings.size = sizeof(settings);
...

Thanks for suggestions, and... alarm sound is driving me crazy... need to move to another room... bye.

PS: you just fill in size member and my library would take care of the rest, with future version it will use default values for missing stuff... etc... this makes coding the library more complicated but as it is destinated to other codes I'll just do it. :)

Link to post

ok found a way to take big icon :

	  #include <shlobj.h> 
#include <shlguid.h>
#include <shellapi.h>
#include <commctrl.h>
#include <commoncontrols.h>

// Get the icon index using SHGetFileInfo
SHFILEINFOW sfi = {0};
SHGetFileInfo(filePath, -1, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX);
// Retrieve the system image list.
// To get the 48x48 icons, use SHIL_EXTRALARGE
// To get the 256x256 icons (Vista only), use SHIL_JUMBO
HIMAGELIST* imageList;
HRESULT hResult = SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void**)&imageList);

if (hResult == S_OK) {
// Get the icon we need from the list. Note that the HIMAGELIST we retrieved
// earlier needs to be casted to the IImageList interface before use.
HICON hIcon;
hResult = ((IImageList*)imageList)->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon);

if (hResult == S_OK) {
// Do something with the icon here.
// For example, in wxWidgets:
wxIcon* icon = new wxIcon();
icon->SetHICON((WXHICON)hIcon);
icon->SetSize(48, 48);
}
}

http://pogopixels.com/blog/getting-the-48x...ile-on-windows/

Link to post

well, :wacko: my icons are bigger now but i have a black shadow in the grid for some icons.

i use the gdi+ Bitmap::FromHIcon(hIcon from previous source) to get a bitmap and extract the bytes for the stack, but it seems that the alpha channel is missing from the imagelist....

do you have some trick for me ?

Link to post
well, :wacko: my icons are bigger now but i have a black shadow in the grid for some icons.

i use the gdi+ Bitmap::FromHIcon(hIcon from previous source) to get a bitmap and extract the bytes for the stack, but it seems that the alpha channel is missing from the imagelist....

do you have some trick for me ?

Gdiplus really sucks at this. It looses the alpha channel :( so you have to do it by hand.

If icon is 32 bits, I get direct access to pixel bits instead:

function TIconProvider.GetAssociatedIcon(filename: WideString): TGpImage;
var
hi : HICON;
ii : TIconInfo;
bi : TBitmapInfo;
pixels : PByteArray;
buffer : array[0..MAX_PATH] of widechar;
name_part : PWideChar;
begin
// Primero determinar la ruta absoluta, parece que Windows no se lleva con las relativas acá
GetFullPathNameW (PWideChar(filename), MAX_PATH, buffer, name_part);
filename := buffer;

// Buscar el icono asociado
hi := unitGetIcon.GetAssociatedIcon (filename);

Result := nil;
If GetIconInfo (hi, ii) Then
begin
FillChar (bi.bmiHeader, sizeof(bi.bmiHeader), 0);
bi.bmiHeader.biSize := sizeof(bi.bmiHeader);
If GetDIBits (fDC, ii.hbmColor, 0, 0, nil, bi, 0) <> 0 Then
begin
If bi.bmiHeader.biBitCount = 32 Then
begin
GetMem (pixels, bi.bmiHeader.biWidth*bi.bmiHeader.biHeight*4);
GetDIBits (fDC, ii.hbmColor, 0, bi.bmiHeader.biHeight, pixels, bi, 0);
If Flip32 (pixels, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight) Then
Result := TGpBitmapExt.Create (bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, pixels);
// NO HACER FreeMem SOBRE LOS PIXELES, AHORA SON DEL GpBitmap
end;
end;
DeleteObject (ii.hbmMask);
DeleteObject (ii.hbmColor);
end;
If Result = nil Then
begin
Result := TGpBitmap.Create (hi);
end;
DestroyIcon (hi);
end;

FillChar -> memset

GetMem -> malloc

TIconInfo -> (windows.h) ICONINFO

TBitmapInfo -> (windows.h) BITMAPINFO

This is for old version of Stacks. For new version I just access icon bytes directly and extract everything by hand, but it seems not to work in many cases (though it allows to extract Vista 256x256 PNG icons under XP, rather impossible by other means). If you need such code I will send it to you, but you'll have to port it from pascal to c++.

Link to post

ok good trick, i've found another way in the site : http://dotnetrix.co.uk/misc.htm

translated in C++ :

Bitmap * IconToAlphaBitmap(HICON ico)
{
ICONINFO ii;
GetIconInfo(ico , &ii);

Bitmap * bmp = Bitmap::FromHBITMAP(ii.hbmColor,0);

DeleteObject(ii.hbmColor);
DeleteObject(ii.hbmMask);

UINT pixel=GetPixelFormatSize(bmp->GetPixelFormat());
if (pixel < 32)
return Bitmap::FromHICON(ico);

BitmapData bmData;
Rect bmBounds(0,0,bmp->GetWidth(),bmp->GetHeight());

bmp->LockBits(&bmBounds,ImageLockModeRead,bmp->GetPixelFormat(),&bmData);

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

bool IsAlphaBitmap = false;

for (int y=0; y <= bmData.Height-1; y++)
{
for (int x=0; x <= bmData.Width-1; x++)
{
ARGB col=*((ARGB*) bmData.Scan0+(bmData.Stride * y) + (4 * x));
Color PixelColor(col);
if (PixelColor.GetA() > 0 & PixelColor.GetA() < 255)
{
IsAlphaBitmap =true;
break;
}
}
if (IsAlphaBitmap) break;
}

bmp->UnlockBits(&bmData);

if (IsAlphaBitmap==true)
{
return dstBitmap;
}
else
{
delete dstBitmap;
return Bitmap::FromHICON(ico);
}
}

it works good for me.

Thank you for your help.

Link to post

@ChristianS:

Hey, actually your way (IconToAlphaBitmap function) seems to be much better. I didn't know Gdiplus preserves alpha information on HBITMAPs, plus it workarounds for when the supposed-to-be-with-alpha-channel 32 bit has no alpha channel at all (isAlphaBitmap variable) then it tries with HICON again.

Link to post
  • 2 weeks later...

I am creating a task list docklet which will show the currently running tasks... I am able to retrieve the running tasks (those listed in the taskbar) and show them using the stack library. I have included a snapshot just for reference.

I have been following your discussion on extracting icons... although I am having no problem to extract and generate the appropiate icon for each running task, the icons I am retrieving are all low-res ones... how could I retrieve a higher quality icon for the running process. Currently I am doing something like:

lpItem->icon = GetWindowIcon(ent.hwnd, ICON_BIG);
.
.
.
Gdiplus::Bitmap *GetWindowIcon(HWND hWnd, DWORD icon_type)
{
HICON hIcon = NULL;
hIcon = (HICON)SendMessage(hWnd, WM_GETICON, (WPARAM) icon_type, 0);
if (hIcon == 0)
hIcon = (HICON)GetClassLong(hWnd, GCL_HICONSM);
if (hIcon == 0)
hIcon = (HICON)GetClassLong(hWnd, GCL_HICON);

if (hIcon == 0)
return NULL;

return IconToAlphaBitmap(hIcon);
}

The bitmaps correspond to the appropiate application, but they look blurry.

post-79521-1238631048_thumb.png

Edited by Smaky
Link to post

You should pass GCL_HICON first (after WM_GETICON), then GCL_HICONSM.

But you'll still get low-res icons probably.

The best I can think of is to use WMI to get executable full path from hwnd, then extract first icon and use that.

Link to post

Already done that... and low-res icons are still being shown. Could you explain the WMI stuff a litte bit more?

You should pass GCL_HICON first (after WM_GETICON), then GCL_HICONSM.

But you'll still get low-res icons probably.

The best I can think of is to use WMI to get executable full path from hwnd, then extract first icon and use that.

Edit:

Never mind, I found a way to retrieve the module (executable) associated with a given running process (thanks to MSDN and to the GetModuleFileNameEx API. Ok, I've got the executable full path... from there what should I do?

Edit 2:

I have modified the procedure to retrieve icons like this:

Gdiplus::Bitmap *GetWindowIcon(HWND hWnd, PTCHAR szFullPath, DWORD icon_type)
{
HICON hIcon = NULL;

SHFILEINFO *lpSfi = new SHFILEINFO;
ZeroMemory(lpSfi, sizeof(SHFILEINFO));
SHGetFileInfo(szFullPath, 0, lpSfi, sizeof(SHFILEINFO), SHGFI_LARGEICON);
hIcon = lpSfi->hIcon;

if (hIcon == NULL)
hIcon = (HICON)SendMessage(hWnd, WM_GETICON, (WPARAM) icon_type, 0);
if (hIcon == NULL)
hIcon = (HICON)GetClassLong(hWnd, GCL_HICON);
if (hIcon == NULL)
hIcon = (HICON)GetClassLong(hWnd, GCL_HICONSM);

if (hIcon == NULL)
return NULL;

if (lpSfi)
delete lpSfi;

return IconToAlphaBitmap(hIcon);
}

but the icons are still low-res and look crappy when setting the stack icon to 128.

Edit 3:

Ok, I finally got it right! thanks to PogoPixel I found how to extract the hi-res icon out of the imagelist that windows keeps. This is the modified code:

Gdiplus::Bitmap *GetWindowIcon(HWND hWnd, PTCHAR szFullPath, DWORD icon_type)
{
HICON hIcon = NULL;

// Get the icon index using SHGetFileInfo
SHFILEINFO *lpSfi = new SHFILEINFO;
ZeroMemory(lpSfi, sizeof(SHFILEINFO));
SHGetFileInfo(szFullPath, 0, lpSfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX);

// Retrieve the system image list.
// To get the 48x48 icons, use SHIL_EXTRALARGE
// To get the 256x256 icons (Vista only), use SHIL_JUMBO
HIMAGELIST *imageList;
HRESULT hResult = SHGetImageList(SHIL_JUMBO, IID_IImageList, (void**)&imageList);
if (hResult == S_OK)
{
// Get the icon we need from the list. Note that the HIMAGELIST we retrieved
// earlier needs to be casted to the IImageList interface before use.
((IImageList*)imageList)->GetIcon(lpSfi->iIcon, ILD_TRANSPARENT, &hIcon);
}

if (hIcon == NULL)
hIcon = (HICON)SendMessage(hWnd, WM_GETICON, (WPARAM) icon_type, 0);
if (hIcon == NULL)
hIcon = (HICON)GetClassLong(hWnd, GCL_HICON);
if (hIcon == NULL)
hIcon = (HICON)GetClassLong(hWnd, GCL_HICONSM);

if (hIcon == NULL)
return NULL;

if (lpSfi)
delete lpSfi;

return IconToAlphaBitmap(hIcon);
}

Edit 4:

Unfortunately, further testing showed that this method does come with several problems... first, although in my dev system it retrieves the executable icons correctly on my host machine it does not work (all icons, no mather what executable is are being shown as the very same hi-res icon as if the image list were empty). Another problem is that for many running processes the executable icon is not always the running app icon (specially for items like explorer folders which do not correspond to the explorer.exe icon). I am not sure how to overcome this... maybe you already have dealt with this.

Edit 5:

Well I have still found no way to retrieve the appropiate hi-res icon for the running process, but thanks to vantha's help and his XWindowDock docklet I think I found a better way to show the tasks. Now it shows a snapshot of the application among the large icon of it. I have included a couple of snapshots here.

Anyway, there are many possibilities here...

1) To get the hi-res icon, how do you do that in the stacks docklet matonga?

2) To show the snapshot only for not minimized apps.

3) Do as now, show an snapshot of all windows (it cames with a price... performance, it takes some time to do the snapshot of minimized apps).

What do you think?

On the other hand, the docket could be much enhanced by adding some features to the stacklib:

1) Highlight of the current hovered item in the grid/fan (Matonga, I believe you might be working on that, if not that would be an excellent feature).

2) left-button click support so I would be able to add a context menu to say, show, hide, close, etc. the currently selected task.

3) Enable/disable state, that dimms (alpha channel) some item, this could help show minimized windows by dimming the a bit (this would be helpful for other scenarios like the RSS Feed docklet, so I could show items already read as dimmed).

Well... i think that's for now.

post-79521-1238695928_thumb.png

post-79521-1238706653_thumb.png

post-79521-1238870424_thumb.png

post-79521-1238870653_thumb.png

Edited by Smaky
Link to post

Wow, those window thumbnails look really cool.

Stacks Docklet has an easier time for icons, I just use IShellFolder::GetUIObjectOf (...) to get the IID_IExtractIcon interface, then I use IExtractIcon::GetIconLocation to get .dll/.ico file (if .dll I get icon index too), then I read the icon at low level instead of using Windows API (this allows me to use hi-res Vista icons under XP).

If you want, I can send you all this code (don't use it in commercial apps! please :) ) (you'll have to translate the code from pascal) just PM me.

Link to post

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.

Link to post

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

Link to post

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.

Link to post

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.

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.

Link to post

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...