Changeset 9f3118f953be…
Parent 925ccc0902ae…
by
Changes to one file · Browse files at 9f3118f953be Showing diff from parent 925ccc0902ae Diff from another changeset...
|
|
@@ -1,793 +0,0 @@ - // TortoiseCVS - a Windows shell extension for easy version control
-
-// Copyright (C) 2001 - Francis Irving
-// <francis@flourish.org> - May 2001
-
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-
-// This program 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 General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-
-#include "StdAfx.h"
-
-//#include "PathUtils.h"
-#include "StringUtils.h"
-//#include "UnicodeStrings.h"
-//#include "TortoiseRegistry.h"
-//#include "Translate.h"
-#include <windows.h>
-#include <map>
-#include <sstream>
-
-// TODO: Put shlwapi.h in mingw32
-#ifndef __GNUC__
-#include <shlwapi.h>
-
-#else
-
-#ifndef DLLVERSIONINFO
-typedef struct _DllVersionInfo
-{
- DWORD cbSize;
- DWORD dwMajorVersion;
- DWORD dwMinorVersion;
- DWORD dwBuildNumber;
- DWORD dwPlatformID;
-} DLLVERSIONINFO;
-#endif
-
-#ifndef DLLGETVERSIONPROC
-typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *);
-#endif
-
-#endif
-
-#include "ShellUtils.h"
-//#include "TortoiseException.h"
-//#include "TortoiseUtils.h"
-//#include "ProcessUtils.h"
-//#include "TortoiseDebug.h"
-//#include "Translate.h"
-
-// Strips the last ID from the list
-LPITEMIDLIST StripLastID(LPCITEMIDLIST pidl)
-{
- TDEBUG_ENTER("StripLastID");
- TDEBUG_TRACE(DisplayNamePIDL(pidl));
- LPMALLOC pMalloc;
- if (!SUCCEEDED(SHGetMalloc(&pMalloc)))
- return NULL;
-
- LPCITEMIDLIST pCurrent = pidl;
- LPCITEMIDLIST pLast = 0;
- DWORD dwSize = 0;
-
- if (pCurrent->mkid.cb == 0)
- {
- return 0;
- }
-
- pLast = pCurrent;
- pCurrent = (LPCITEMIDLIST) (((LPBYTE) pCurrent) + pCurrent->mkid.cb);
-
- while (pCurrent->mkid.cb != 0)
- {
- dwSize += pLast->mkid.cb;
- pLast = pCurrent;
- pCurrent = (LPITEMIDLIST) (((LPBYTE) pCurrent) + pCurrent->mkid.cb);
- }
-
- LPITEMIDLIST pidlParent = (LPITEMIDLIST) pMalloc->Alloc(dwSize + sizeof(USHORT));
- if (pidlParent != 0)
- {
- CopyMemory(pidlParent, pidl, dwSize);
- *((USHORT*) (((LPBYTE) pidlParent) + dwSize)) = 0;
- }
- TDEBUG_TRACE(DisplayNamePIDL(pidlParent));
- pMalloc->Release();
- return pidlParent;
-}
-
-
-
-
-// Get the last ID from the list
-LPITEMIDLIST GetLastID(LPCITEMIDLIST pidl)
-{
- LPMALLOC pMalloc;
- if (!SUCCEEDED(SHGetMalloc(&pMalloc)))
- return NULL;
-
- LPCITEMIDLIST pCurrent = pidl;
- LPCITEMIDLIST pLast = 0;
-
- while (pCurrent->mkid.cb != 0)
- {
- pLast = pCurrent;
- pCurrent = (LPITEMIDLIST) (((LPBYTE) pCurrent) + pCurrent->mkid.cb);
- }
-
- LPITEMIDLIST pidlLast = (LPITEMIDLIST) pMalloc->Alloc(pLast->mkid.cb + sizeof(USHORT));
- if (pidlLast != 0)
- {
- CopyMemory(pidlLast, pLast, pLast->mkid.cb);
- *((USHORT*) (((LPBYTE) pidlLast) + pLast->mkid.cb)) = 0;
- }
-
- pMalloc->Release();
- return pidlLast;
-}
-
-
-// Bind to parent
-IShellFolder* BindToParent(LPCITEMIDLIST pidl)
-{
- TDEBUG_ENTER("BindToParent");
- IShellFolder* psfDesktop = 0;
- IShellFolder* psfResult = 0;
- HRESULT hr = 0;
-
- LPITEMIDLIST pidlParent = StripLastID(pidl);
- TDEBUG_TRACE(DisplayNamePIDL(pidlParent));
- if (!pidlParent)
- {
- goto Cleanup;
- }
-
- hr = SHGetDesktopFolder(&psfDesktop);
- if (FAILED(hr))
- {
- goto Cleanup;
- }
-
- if (IsDesktopFolder(pidlParent))
- {
- psfResult = psfDesktop;
- psfDesktop = 0;
- }
- else
- {
- hr = psfDesktop->BindToObject(pidlParent, 0, IID_IShellFolder,
- (LPVOID*) &psfResult);
- if (FAILED(hr))
- {
- goto Cleanup;
- }
- }
-
-
-Cleanup:
- if (psfDesktop)
- psfDesktop->Release();
-
- if (pidlParent)
- ItemListFree(pidlParent);
-
- return psfResult;
-}
-
-
-
-std::string DisplayNamePIDL(LPCITEMIDLIST pidl)
-{
- SHFILEINFOA sfi;
- if (SHGetFileInfoA((LPCSTR) pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_DISPLAYNAME) == 0)
- {
- ASSERT(false);
- return "<DisplayNamePIDL failed>";
- }
-
- return sfi.szDisplayName;
-}
-
-
-
-
-bool LaunchCommand(const std::string& command, bool waitForEnd, bool minimized)
-{
- TDEBUG_ENTER("LaunchCommand");
- TDEBUG_TRACE("Command: " << command);
- PROCESS_INFORMATION processInfo;
- STARTUPINFOA startupInfo;
- memset(&startupInfo, 0, sizeof(startupInfo));
- startupInfo.cb = sizeof(startupInfo);
- startupInfo.dwFlags = minimized ? STARTF_USESHOWWINDOW : 0;
- startupInfo.wShowWindow = SW_SHOWMINIMIZED;
- int res = CreateProcessA(0,
- const_cast<char*>(command.c_str()),
- 0, 0,
- FALSE,
- //WindowsPlatformIsNT() ? CREATE_NO_WINDOW : 0,
- 0,
- 0, 0, &startupInfo, &processInfo);
- TDEBUG_TRACE("res " << res);
- if (res == 0)
- {
- return false;
- }
-
- if (waitForEnd)
- {
- TDEBUG_TRACE("Waiting...");
-#if defined(TDEBUG_ON)
- DWORD dw =
-#endif
- WaitWithMsgQueue(1, &processInfo.hProcess, true, INFINITE);
- TDEBUG_TRACE("LaunchCommand: dw " << dw);
- }
-
- CloseHandle(processInfo.hProcess);
- CloseHandle(processInfo.hThread);
- return true;
-}
-
-bool FileIsViewable(const std::string& filename)
-{
- // If no application is associated with the file, fail
- char buf[MAX_PATH];
- if (int(FindExecutableA(filename.c_str(), "", buf)) == SE_ERR_NOASSOC)
- return false;
- // Fail if the file is associated with itself (i.e. executable)
- if (!strcmpi(filename.c_str(), buf))
- return false;
- return true;
-}
-
-bool LaunchFile(const std::string& filename, bool waitForEnd)
-{
- TDEBUG_ENTER("LaunchFile");
-
- if (!FileIsViewable(filename))
- return false;
-
- static const char* textExtensions[] =
- {
- "c", // C source
- "cpp", // C++ source
- "h", // C/C++ header
- "hpp", // C++ header
- "txt", // Text file
- 0
- };
- bool isTextFile = false;
- std::string ext = GetExtension(filename);
- for (const char** p = textExtensions; *p; ++p)
- if (!strcmp(*p, ext.c_str()))
- {
- isTextFile = true;
- break;
- }
-
- SHELLEXECUTEINFOA sei;
- ZeroMemory(&sei, sizeof(sei));
- sei.cbSize = sizeof(sei);
- sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
- sei.lpFile = filename.c_str();
- sei.nShow = SW_SHOW;
- sei.lpVerb = isTextFile ? "open" : "edit";
- if (!ShellExecuteExA(&sei))
- {
- if (sei.hInstApp == reinterpret_cast<HINSTANCE>(SE_ERR_NOASSOC))
- {
- // No association for this extension (typically when file has no extension)
- std::ostringstream ss;
- ss << "notepad " << filename;
- return LaunchCommand(ss.str(), waitForEnd);
- }
- ASSERT(sei.hInstApp > reinterpret_cast<HINSTANCE>(32));
- return false;
- }
-
- if (waitForEnd && sei.hProcess != 0)
- {
- TDEBUG_TRACE("Waiting...");
-#if defined(TDEBUG_ON)
- DWORD dw =
-#endif
- WaitWithMsgQueue(1, &sei.hProcess, true, INFINITE);
- TDEBUG_TRACE("LaunchCommand: dw " << dw);
- }
-
- if (sei.hProcess != 0)
- {
- CloseHandle(sei.hProcess);
- }
- return true;
-}
-
-
-// Test if PIDL points to a special folder
-bool IsSpecialFolder(LPCITEMIDLIST pidl, int nFolder)
-{
- HRESULT hr;
- bool result = false;
- LPITEMIDLIST mypidl = 0;
- hr = SHGetSpecialFolderLocation(NULL, nFolder, &mypidl);
- if (FAILED(hr))
- {
- goto Cleanup;
- }
-
- result = IsEqualPIDL(pidl, mypidl);
-
-Cleanup:
- if(mypidl)
- ItemListFree(mypidl);
-
- return result;
-}
-
-
-// Get IShellFolder from PIDL
-IShellFolder* GetIShellFolderFromPIDL(LPCITEMIDLIST pidl)
-{
- HRESULT hr;
- IShellFolder* psfDesktop = 0;
- IShellFolder* psfResult = 0;
- hr = SHGetDesktopFolder(&psfDesktop);
- if (SUCCEEDED(hr))
- {
- hr = psfDesktop->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*) &psfResult);
- if (FAILED(hr))
- {
- psfResult = 0;
- goto Cleanup;
- }
- }
-
-Cleanup:
- if (psfDesktop)
- psfDesktop->Release();
- return psfResult;
-}
-
-
-
-
-// Rebuild icons
-bool RebuildIcons()
-{
- TDEBUG_ENTER("RebuildIcons");
- const int BUFFER_SIZE = 1024;
-
- HKEY hRegKey = 0;
- LONG lRegResult = RegOpenKeyExA(HKEY_CURRENT_USER, "Control Panel\\Desktop\\WindowMetrics",
- 0, KEY_READ | KEY_WRITE, &hRegKey);
- if (lRegResult != ERROR_SUCCESS)
- {
- TDEBUG_TRACE("Failed to open WindowMetrics key");
- return false;
- }
-
- char* buf = new char[BUFFER_SIZE];
-
- // Before Win2k, we're going to change the icon size, otherwise the color depht
- std::string sRegValueName;
- bool bUseSize = false;
- if (WindowsVersionIs2KOrHigher())
- sRegValueName = "Shell Icon BPP";
- else
- {
- bUseSize = true;
- sRegValueName = "Shell Icon Size";
- }
-
- // Read registry value
- DWORD dwSize = BUFFER_SIZE;
- lRegResult = RegQueryValueExA(hRegKey, sRegValueName.c_str(), NULL, NULL, (LPBYTE) buf, &dwSize);
- if (lRegResult == ERROR_FILE_NOT_FOUND)
- {
- strncpy(buf, "32", BUFFER_SIZE);
- }
- else if (lRegResult != ERROR_SUCCESS)
- {
- TDEBUG_TRACE("Failed to read " << sRegValueName);
- RegCloseKey(hRegKey);
- return false;
- }
-
-
- // Change registry value
- DWORD dwRegValue = atoi(buf);
- DWORD dwRegValueTemp = 0;
- if (!bUseSize)
- {
- if (dwRegValue == 4)
- dwRegValueTemp = 32;
- else
- dwRegValueTemp = 4;
- }
- else
- {
- if (dwRegValue == 31)
- dwRegValueTemp = 32;
- else
- dwRegValueTemp = 31;
- }
-
- dwSize = _snprintf(buf, BUFFER_SIZE, "%d", dwRegValueTemp) + 1;
- lRegResult = RegSetValueExA(hRegKey, sRegValueName.c_str(), 0, REG_SZ, (LPBYTE) buf, dwSize);
- if (lRegResult != ERROR_SUCCESS)
- {
- TDEBUG_TRACE("Failed to change " << sRegValueName);
- RegCloseKey(hRegKey);
- delete[] buf;
- return false;
- }
-
-
- // Update all windows
- PDWORD dwResult;
- SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS,
- 0, SMTO_ABORTIFHUNG, 5000, reinterpret_cast<PDWORD_PTR>(&dwResult));
-
- // Reset registry value
- dwSize = _snprintf(buf, BUFFER_SIZE, "%d", dwRegValue) + 1;
- lRegResult = RegSetValueExA(hRegKey, sRegValueName.c_str(), 0, REG_SZ, (LPBYTE) buf, dwSize);
- if(lRegResult != ERROR_SUCCESS)
- {
- TDEBUG_TRACE("Failed to reset " << sRegValueName);
- RegCloseKey(hRegKey);
- delete[] buf;
- return false;
- }
-
- // Update all windows
- SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS,
- 0, SMTO_ABORTIFHUNG, 5000, reinterpret_cast<PDWORD_PTR>(&dwResult));
-
- RegCloseKey(hRegKey);
- delete[] buf;
- return true;
-}
-
-
-// Notify shell of change
-void ShellNotifyUpdateFile(const std::string& sFilename)
-{
- std::vector<std::string> vFiles;
- vFiles.push_back(sFilename);
- ShellNotifyUpdateFiles(vFiles);
-}
-
-
-// Notify shell of change
-void ShellNotifyUpdateFiles(const std::vector<std::string>& sFilenames)
-{
- IMalloc *pMalloc = 0;
- IShellFolder *pFolder = 0;
- LPITEMIDLIST pidl = 0;
- std::vector<std::string>::const_iterator it = sFilenames.begin();
- std::wstring wsFilename;
- WIN32_FIND_DATAA fd;
- HANDLE hFindFile = INVALID_HANDLE_VALUE;
- bool bUseWildcards = false;
-
- // Get malloc
- if (!SUCCEEDED(SHGetMalloc(&pMalloc)))
- goto Cleanup;
-
- // Get desktop folder
- if (!SUCCEEDED(SHGetDesktopFolder(&pFolder)))
- goto Cleanup;
-
- while (it != sFilenames.end())
- {
- // Resolve wildcards
- bUseWildcards = (it->find_first_of("*?") != std::string::npos);
- if (bUseWildcards)
- {
- hFindFile = FindFirstFileA(it->c_str(), &fd);
- if (hFindFile == INVALID_HANDLE_VALUE)
- {
- it++;
- continue;
- }
- }
-
- do
- {
- // Convert filename to widestring
- if (bUseWildcards)
- {
- std::string s = EnsureTrailingDelimiter(StripLastPart(*it)) + fd.cFileName;
- wsFilename = MultibyteToWide(s, 0);
- }
- else
- {
- wsFilename = MultibyteToWide(*it, 0);
- }
-
- // Convert filename to ID list
- if (!SUCCEEDED(pFolder->ParseDisplayName(0, 0,
- (LPWSTR) wsFilename.c_str(), 0, &pidl, 0)))
- goto Cleanup;
-
- // Notify shell
- SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_IDLIST | SHCNF_FLUSH, pidl, 0);
-
- // Release memory
- pMalloc->Free(pidl);
- pidl = 0;
-
- } while (bUseWildcards && FindNextFileA(hFindFile, &fd));
-
- if (bUseWildcards)
- {
- FindClose(hFindFile);
- hFindFile = INVALID_HANDLE_VALUE;
- }
-
- it++;
- }
-
-Cleanup:
- if (hFindFile != INVALID_HANDLE_VALUE)
- FindClose(hFindFile);
- if (pidl && pMalloc)
- pMalloc->Free(pidl);
- if (pFolder)
- pFolder->Release();
- if (pMalloc)
- pMalloc->Release();
-}
-
-
-// Notify shell of change
-void ShellNotifyUpdateFiles(const std::string& sDirname,
- const std::vector<std::string>& sFilenames)
-{
- std::string sFilename;
- std::vector<std::string> vFiles;
- std::vector<std::string>::const_iterator it = sFilenames.begin();
- while (it != sFilenames.end())
- {
- sFilename = EnsureTrailingDelimiter(sDirname) + *it;
- vFiles.push_back(sFilename);
- it++;
- }
- ShellNotifyUpdateFiles(vFiles);
-}
-
-
-
-void ShellNotifyUpdateDir(const std::string& /* sDirname */)
-{
-/* std::wstring wsDirname = MultibyteToWide(sDirname);
- WCHAR buf[_MAX_PATH];
- wcsncpy(buf, wsDirname.c_str(), _MAX_PATH);
- SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH, buf, NULL);*/
-}
-
-
-
-// Wait while processing messages
-DWORD WaitWithMsgQueue(DWORD nCount, const HANDLE* pHandles, bool fWaitAll,
- DWORD dwMilliseconds)
-{
- DWORD dw, tcNow, tcEnd, dwTimeToWait;
- DWORD dwResult = 0;
- MSG msg;
- DWORD i;
- bool *ba = 0;
- HANDLE myHandles[MAXIMUM_WAIT_OBJECTS];
- unsigned int myCount;
-
- // Initialize handle array
- for (i = 0; i < nCount; i++)
- {
- myHandles[i] = pHandles[i];
- }
- myCount = nCount;
-
- tcNow = GetTickCount();
- tcEnd = tcNow + dwMilliseconds;
-
- bool bRepeat = true;
- while (bRepeat)
- {
- if ((dwMilliseconds != INFINITE) && (tcNow >= tcEnd))
- {
- dwResult = WAIT_TIMEOUT;
- goto Cleanup;
- }
-
- if (dwMilliseconds != INFINITE)
- {
- dwTimeToWait = tcEnd - tcNow;
- }
- else
- {
- dwTimeToWait = INFINITE;
- }
-
- dw = MsgWaitForMultipleObjects(myCount, myHandles, false, dwTimeToWait, QS_ALLINPUT);
- // Object got signaled
- if (dw < (WAIT_OBJECT_0 + myCount))
- {
- if (fWaitAll)
- {
- // Remove object
- i = dw - WAIT_OBJECT_0;
- myCount--;
- for (unsigned int j = i; j < myCount - 1 && myCount > 0; j++)
- {
- myHandles[j] = myHandles[j + 1];
- }
-
- // Exit if all objects have been signaled
- if (myCount == 0)
- {
- dwResult = WAIT_OBJECT_0;
- goto Cleanup;
- }
- }
- else
- {
- dwResult = dw;
- goto Cleanup;
- }
- }
- // Got message
- else if (dw == (WAIT_OBJECT_0 + nCount))
- {
- while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
- {
- if (msg.message == WM_QUIT)
- {
- dwResult = dw;
- goto Cleanup;
- }
-
- DispatchMessage(&msg);
-
- // Check for timeout
- tcNow = GetTickCount();
- if ((dwMilliseconds != INFINITE) && (tcNow >= tcEnd))
- {
- dwResult = WAIT_TIMEOUT;
- goto Cleanup;
- }
- }
- }
- // WAIT timed out
- else if (dw == WAIT_TIMEOUT)
- {
- dwResult = dw;
- goto Cleanup;
- }
- // WAIT failed
- else
- {
- dwResult = dw;
- goto Cleanup;
- }
-
- tcNow = GetTickCount();
- }
-
-Cleanup:
- if (ba)
- delete ba;
- return dwResult;
-}
-
-// Get path for iconset
-std::string GetIconSetPath(const std::string& iconSet)
-{
- // No icons => empty path
- if (iconSet.empty())
- return "";
-
- std::string dir = GetTortoiseDirectory();
- dir = EnsureTrailingDelimiter(dir) + "icons\\" + iconSet;
- return EnsureTrailingDelimiter(dir);
-}
-
-
-// Get name of iconset
-wxString GetIconSetName(const std::string& iconSet)
-{
- // No icons => empty path
- if (iconSet.empty())
- return wxT("");
-
- std::string key("Icons\\");
- key += iconSet;
- wxString name(TortoiseRegistry::ReadWxString(key));
- return wxGetTranslation(name);
-}
-
-// Get attributes for file (contains bugfix for SHGetFileInfo)
-BOOL MyShellGetFileAttr(const void* data, DWORD *attr, bool bIsPidl)
-{
- TDEBUG_ENTER("MyShellGetFileAttr");
-#ifndef UNICODE
- // Workaround for NT4 bug: SHGetFileInfoA doesn't work correclty,
- // so use SHGetFileInfoW
-
- if (WindowsVersionIsNT4())
- {
- TDEBUG_TRACE("Windows NT4 workaround");
- SHFILEINFOW fi;
- std::wstring ws;
- DWORD dwFlags = SHGFI_ATTRIBUTES;
- if (attr == 0)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return false;
- }
- if (*attr != 0)
- {
- TDEBUG_TRACE("Attributes: " << *attr);
- fi.dwAttributes = *attr;
- dwFlags |= SHGFI_ATTR_SPECIFIED;
- }
- if (bIsPidl)
- {
- TDEBUG_TRACE("It's a PIDL");
- dwFlags |= SHGFI_PIDL;
- }
- else
- {
- TDEBUG_TRACE("It's a path:" << (const char *) data);
- ws = MultibyteToWide((const char *) data, 0);
- data = ws.c_str();
- }
-
- DWORD dwResult = SHGetFileInfoW((LPWSTR) data, 0, &fi, sizeof(fi),
- dwFlags);
- *attr = fi.dwAttributes;
- return (dwResult != 0);
- }
-#endif
-
- SHFILEINFOA fi;
- DWORD dwFlags = SHGFI_ATTRIBUTES;
- if (attr != 0)
- {
- fi.dwAttributes = *attr;
- dwFlags |= SHGFI_ATTR_SPECIFIED;
- }
- if (bIsPidl)
- dwFlags |= SHGFI_PIDL;
-
- DWORD dwResult = SHGetFileInfoA((LPCSTR) data, 0, &fi, sizeof(fi), dwFlags);
- *attr = fi.dwAttributes;
- return (dwResult != 0);
-}
-
-
-// Get attributes for file (contains bugfix for SHGetFileInfo)
-BOOL ShellGetFileAttributes(const char* filename, DWORD *attr)
-{
- return MyShellGetFileAttr(filename, attr, false);
-}
-
-
-// Get attributes for file (contains bugfix for SHGetFileInfo)
-BOOL ShellGetFileAttributesPidl(LPCITEMIDLIST pidl, DWORD *attr)
-{
- return MyShellGetFileAttr(pidl, attr, true);
-}
-
-
-// Get icon size
-BOOL ShellGetIconSize(UINT iconsize, int *width, int *height)
-{
- SHFILEINFOA sfi;
- HIMAGELIST himg = (HIMAGELIST) SHGetFileInfoA("*.txt", FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi),
- SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_SHELLICONSIZE | iconsize);
-
- return ImageList_GetIconSize(himg, width, height);
-}
|
Loading...