|  | /* | 
|  | *  OLE32 Initialization | 
|  | * | 
|  | * Copyright 2000 Huw D M Davies for CodeWeavers | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  | #include "wine/port.h" | 
|  |  | 
|  | #include <stdarg.h> | 
|  | #include <stdio.h> | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "wingdi.h" | 
|  | #include "winuser.h" | 
|  | #include "winnls.h" | 
|  | #include "objbase.h" | 
|  | #include "ole2.h" | 
|  | #include "wine/debug.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(ole); | 
|  |  | 
|  | #define HIMETRIC_INCHES 2540 | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		OleMetafilePictFromIconAndLabel (OLE32.@) | 
|  | */ | 
|  | HGLOBAL WINAPI OleMetafilePictFromIconAndLabel(HICON hIcon, LPOLESTR lpszLabel, | 
|  | LPOLESTR lpszSourceFile, UINT iIconIndex) | 
|  | { | 
|  | METAFILEPICT mfp; | 
|  | HDC hdc; | 
|  | HGLOBAL hmem = NULL; | 
|  | LPVOID mfdata; | 
|  | static const char szIconOnly[] = "IconOnly"; | 
|  | SIZE text_size = { 0, 0 }; | 
|  | INT width; | 
|  | INT icon_width; | 
|  | INT icon_height; | 
|  | INT label_offset; | 
|  | HDC hdcScreen; | 
|  | LOGFONTW lf; | 
|  | HFONT font; | 
|  |  | 
|  | TRACE("%p %p %s %d\n", hIcon, lpszLabel, debugstr_w(lpszSourceFile), iIconIndex); | 
|  |  | 
|  | if( !hIcon ) | 
|  | return NULL; | 
|  |  | 
|  | if (!SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0)) | 
|  | return NULL; | 
|  |  | 
|  | font = CreateFontIndirectW(&lf); | 
|  | if (!font) | 
|  | return NULL; | 
|  |  | 
|  | hdc = CreateMetaFileW(NULL); | 
|  | if( !hdc ) | 
|  | { | 
|  | DeleteObject(font); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | SelectObject(hdc, font); | 
|  |  | 
|  | ExtEscape(hdc, MFCOMMENT, sizeof(szIconOnly), szIconOnly, 0, NULL); | 
|  |  | 
|  | icon_width = GetSystemMetrics(SM_CXICON); | 
|  | icon_height = GetSystemMetrics(SM_CYICON); | 
|  | /* FIXME: should we give the label a bit of padding here? */ | 
|  | label_offset = icon_height; | 
|  | if (lpszLabel) | 
|  | { | 
|  | HFONT screen_old_font; | 
|  | /* metafile DCs don't support GetTextExtentPoint32, so size the font | 
|  | * using the desktop window DC */ | 
|  | hdcScreen = GetDC(NULL); | 
|  | screen_old_font = SelectObject(hdcScreen, font); | 
|  | GetTextExtentPoint32W(hdcScreen, lpszLabel, lstrlenW(lpszLabel), &text_size); | 
|  | SelectObject(hdcScreen, screen_old_font); | 
|  | ReleaseDC(NULL, hdcScreen); | 
|  |  | 
|  | width = 3 * icon_width; | 
|  | } | 
|  | else | 
|  | width = icon_width; | 
|  |  | 
|  | SetMapMode(hdc, MM_ANISOTROPIC); | 
|  | SetWindowOrgEx(hdc, 0, 0, NULL); | 
|  | SetWindowExtEx(hdc, width, label_offset + text_size.cy, NULL); | 
|  |  | 
|  | /* draw the icon centred */ | 
|  | DrawIcon(hdc, (width-icon_width) / 2, 0, hIcon); | 
|  | if(lpszLabel) | 
|  | /* draw the label centred too, if provided */ | 
|  | TextOutW(hdc, (width-text_size.cx) / 2, label_offset, lpszLabel, lstrlenW(lpszLabel)); | 
|  |  | 
|  | if (lpszSourceFile) | 
|  | { | 
|  | char szIconIndex[10]; | 
|  | int path_length = WideCharToMultiByte(CP_ACP,0,lpszSourceFile,-1,NULL,0,NULL,NULL); | 
|  | if (path_length > 1) | 
|  | { | 
|  | char * szPath = CoTaskMemAlloc(path_length * sizeof(CHAR)); | 
|  | if (szPath) | 
|  | { | 
|  | WideCharToMultiByte(CP_ACP,0,lpszSourceFile,-1,szPath,path_length,NULL,NULL); | 
|  | ExtEscape(hdc, MFCOMMENT, path_length, szPath, 0, NULL); | 
|  | CoTaskMemFree(szPath); | 
|  | } | 
|  | } | 
|  | snprintf(szIconIndex, 10, "%u", iIconIndex); | 
|  | ExtEscape(hdc, MFCOMMENT, strlen(szIconIndex)+1, szIconIndex, 0, NULL); | 
|  | } | 
|  |  | 
|  | mfp.mm = MM_ANISOTROPIC; | 
|  | hdcScreen = GetDC(NULL); | 
|  | mfp.xExt = MulDiv(width, HIMETRIC_INCHES, GetDeviceCaps(hdcScreen, LOGPIXELSX)); | 
|  | mfp.yExt = MulDiv(label_offset + text_size.cy, HIMETRIC_INCHES, GetDeviceCaps(hdcScreen, LOGPIXELSY)); | 
|  | ReleaseDC(NULL, hdcScreen); | 
|  | mfp.hMF = CloseMetaFile(hdc); | 
|  | DeleteObject(font); | 
|  | if( !mfp.hMF ) | 
|  | return NULL; | 
|  |  | 
|  | hmem = GlobalAlloc( GMEM_MOVEABLE, sizeof(mfp) ); | 
|  | if( !hmem ) | 
|  | { | 
|  | DeleteMetaFile(mfp.hMF); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | mfdata = GlobalLock( hmem ); | 
|  | if( !mfdata ) | 
|  | { | 
|  | GlobalFree( hmem ); | 
|  | DeleteMetaFile(mfp.hMF); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | memcpy(mfdata,&mfp,sizeof(mfp)); | 
|  | GlobalUnlock( hmem ); | 
|  |  | 
|  | TRACE("returning %p\n",hmem); | 
|  |  | 
|  | return hmem; | 
|  | } |