Get bytes/char* from hIcon/hBitmap - c++

I'm working on a C/S application, Server in C++ and Client in C#, I need to send some information about current running processes and related icon.
I get icon file thanks to EnumWindows with this code inside the callback...
// Get the window icon
HICON hIcon = (HICON)(::SendMessageW(hWnd, WM_GETICON, ICON_SMALL, 0));
if (hIcon == 0) {
// Alternative method. Get from the window class
hIcon = reinterpret_cast<HICON>(::GetClassLongPtrW(hWnd, GCLP_HICONSM));
}
// Alternative: get the first icon from the main module
if (hIcon == 0) {
hIcon = ::LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(0));
}
// Alternative method. Use OS default icon
if (hIcon == 0) {
hIcon = ::LoadIcon(0, IDI_APPLICATION);
}
OK, now I have the Icon and I can "print" it (simply for check) with DrawIcon().
My question is: How to get bytes starting from this?
I need a buffer to send this data to my Client and CONVERT the same data to display icon in a list (icon + process_name). So, I need to get bytes of this icon/hIcon (or bitmap/hBitmap, etc.)
(Of course I need help for server side.)
I think is good to copy the icon in a temp buffer to get bytes but nothing works.
Any help would be appreciated.
EDIT:
#DavidHeffernan thank you for reply. I found this: Converting-DDB-to-DIB through StackOverflow's past questions (sorry if is bad to post external links).
Now, with GetDIBits() I have in the fifth param the LPVOID lpvBits , that is "A pointer to a buffer to receive the bitmap data msdn - GetDIBits()"
Now, How Should I send from lpvBits? What's about Bitmap Size?

I've found something on MSDN and StackOverflow and it helped me: link;
#include "stdafx.h"
#include <windows.h>
#include <olectl.h>
#pragma comment(lib, "oleaut32.lib")
HRESULT SaveIcon(HICON hIcon, const wchar_t* path) {
// Create the IPicture intrface
PICTDESC desc = { sizeof(PICTDESC) };
desc.picType = PICTYPE_ICON;
desc.icon.hicon = hIcon;
IPicture* pPicture = 0;
HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)&pPicture);
if (FAILED(hr)) return hr;
// Create a stream and save the image
IStream* pStream = 0;
CreateStreamOnHGlobal(0, TRUE, &pStream);
LONG cbSize = 0;
hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize);
// Write the stream content to the file
if (!FAILED(hr)) {
HGLOBAL hBuf = 0;
GetHGlobalFromStream(pStream, &hBuf);
void* buffer = GlobalLock(hBuf);
HANDLE hFile = CreateFile(path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (!hFile) hr = HRESULT_FROM_WIN32(GetLastError());
else {
DWORD written = 0;
WriteFile(hFile, buffer, cbSize, &written, 0);
CloseHandle(hFile);
}
GlobalUnlock(buffer);
}
// Cleanup
pStream->Release();
pPicture->Release();
return hr;
}
int _tmain(int argc, _TCHAR* argv[])
{
HICON hIcon = (HICON)LoadImage(0, L"c:\\windows\\system32\\perfcentercpl.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
if (!hIcon) return GetLastError();
HRESULT hr = SaveIcon(hIcon, L"c:\\temp\\test.ico");
return hr;
}
Thanks to SaveIcon() I can save it and after, when needed, I can open it as binary file and send it via socket.

Related

How to extract file icon and save as .ico while preserving color depth in C++?

I am able to extract a file's icon and save it using the script below, but the script saves the icons in grey (seems to be 4 bit color depth).
How can I save icons while preserving their original color depth?
using namespace std;
#include <iostream>
#include <string>
#include <fstream>
#include <windows.h>
#include "commctrl.h"
#pragma comment(lib, "comctl32.lib")
#include <olectl.h>
#pragma comment(lib, "oleaut32.lib")
HRESULT SaveIcon(HICON hIcon, PCTSTR path) {
// Create the IPicture intrface
PICTDESC desc = { sizeof(PICTDESC) };
desc.picType = PICTYPE_ICON;
desc.icon.hicon = hIcon;
IPicture* pPicture = 0;
HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)& pPicture);
if (FAILED(hr)) return hr;
// Create a stream and save the image
IStream* pStream = 0;
CreateStreamOnHGlobal(0, TRUE, &pStream);
LONG cbSize = 0;
hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize);
// Write the stream content to the file
if (!FAILED(hr)) {
HGLOBAL hBuf = 0;
GetHGlobalFromStream(pStream, &hBuf);
void* buffer = GlobalLock(hBuf);
HANDLE hFile = CreateFile(path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (!hFile) hr = HRESULT_FROM_WIN32(GetLastError());
else {
DWORD written = 0;
WriteFile(hFile, buffer, cbSize, &written, 0);
CloseHandle(hFile);
}
GlobalUnlock(buffer);
}
// Cleanup
pStream->Release();
pPicture->Release();
return hr;
}
HICON GetIcon(PCTSTR pszFile)
{
SHFILEINFO sfi;
HIMAGELIST himl = reinterpret_cast<HIMAGELIST>(
SHGetFileInfo(pszFile, 0, &sfi, sizeof(sfi),
SHGFI_SYSICONINDEX));
if (himl) {
return ImageList_GetIcon(himl, sfi.iIcon, ILD_NORMAL);
}
else {
return NULL;
}
}
int main()
{
string fileBaseName = "appName";
wstring fileBaseNameWSTRING(fileBaseName.begin(), fileBaseName.end());
HICON hIcon = GetIcon((fileBaseNameWSTRING + L".lnk").c_str());
if (hIcon == NULL) {
cout << "GetIcon failed" << endl;
return 1;
}
else {
HRESULT hr = SaveIcon(hIcon, (L"temp\\" + fileBaseNameWSTRING + L".ico").c_str());
return hr;
}
}
The SaveIcon function was taken from this page:
How can I save HICON to an .ico file?
Generally, icons contain multiple original bit depths, also multiple resolutions. APIs which return HICON won’t do, they pick a single image from the icon.
If you want the complete one, change SHGFI_SYSICONINDEX to SHGFI_ICONLOCATION, you’ll get path to a DLL with icon + index of the icon.
Load the DLL, ideally with LoadLibraryEx API and LOAD_LIBRARY_AS_DATAFILE option.
Then call resource APIs, FindResource / LoadResource / SizeofResource / LockResource, to get the source data for the icon.

How to load GDI::Image (GIF) from Resource in c++(winapi)?

I'm making a window c++ with winapi(non-MFC) and showing gif. For this Im using GDI++. I'm loading a gif to GDI::Image from the path, but I want to load it from resources. How can I do it?
hMWDC = GetDC(hWnd);
pGphcs = new Graphics(hMWDC);
WCHAR path[MAX_PATH];
GetModuleFileNameW(NULL, path, MAX_PATH);
PathRemoveFileSpecW(path);
PathAppendW(path, L"gifs\\test.gif");
pImg = new Image(path);
if (pImg) {
nFrmCnt = pImg->GetFrameCount(&FrameDimensionTime);
SetTimer(hWnd, DRAW_ANIM, 100, NULL);
}
case WM_TIMER:
if (wParam == DRAW_ANIM)
{
pImg->SelectActiveFrame(&FrameDimensionTime, nFrm);
Rect DRC(0, 0, pImg->GetWidth(), pImg->GetHeight());
pGphcs->Clear(Color(128, 128, 128));
pGphcs->DrawImage(pImg, DRC);
if (nFrm < (nFrmCnt - 1)) nFrm++; else nFrm = 0;
}
break;
There is an Image constructor that accepts an IStream*.
You can create a stream by calling SHCreateMemStream on the raw buffer of a resource, which can be obtained by calling FindResource/LoadResource/LockResource and SizeOfResource.
Add the GIF file to your app's resources at compile time. For instance, by compiling an .rc file similar to below into a .res file that you can then link into your executable (some compilers/IDEs have tools to automate this step):
Resources.rh
#define MY_GIF_ID 100
Resources.rc
#include "Resources.rh"
MY_GIF_ID RCDATA "gifs\\test.gif"
Then, you can obtain a pointer to the raw bytes of the resource at runtime.
#include "Resources.rh"
HMODULE hMod = GetModuleHandle(NULL);
HRSRC hRes = FindResource(hMod, MAKEINTRESOURCE(MY_GIF_ID), RT_RCDATA);
if (!hRes) { ... error handling ... }
HGLOBAL hGlobal = LoadResource(hMod, hRes);
if (!hGlobal) { ... error handling ... }
void *pResData = LockResource(hGlobal);
if (!pResData) { ... error handling ... }
DWORD dwResData = SizeofResource(hMod, hRes);
See MSDN for more details:
Introduction to Resources
Finding and Loading Resources
And then finally, pass the resource bytes to the Image constructor that takes an IStream* as input:
#include <shlwapi.h>
IStream *pStream = SHCreateMemStream((BYTE*)pResData, dwResData);
if (!pStream) { ... error handling ... }
pImg = new Image(pStream);
pStream->Release();

Moving UWP application window by native c++ code

I am trying to control the size and position of a UWP APP (Windows Mixed Reality Portal) via a sepate app. In my case, I am using a console app for simplicity. A Command script would also work for what I want to achieve.
I have tried Windows api such as MoveWindow,SetWindowPos but they do not work as expected and GetWindowRect returns a 0,0,0,0 rect. I can get the window handle but not change the size/position.
My reason for doing this is to send virtual mouse keys to the app in order to initialise the front position of the Windows Mixed Reality system. Sending the virtual keys are fine but I am having trouble automating shifting of the position of the uwp app itself.
#include <iostream>
#include <ShObjIdl.h>
#include <atlbase.h>
#include <tlhelp32.h>
BOOL CALLBACK EnumWindowsProcBack(HWND windowHandle, LPARAM lParam) {
DWORD searchedProcessId = (DWORD)lParam; // This is the process ID we search for (passed from BringToForeground as lParam)
DWORD windowProcessId = 0;
GetWindowThreadProcessId(windowHandle, &windowProcessId); // Get process ID of the window we just found
if (searchedProcessId == windowProcessId) { // Is it the process we care about?
//std::cout << "moving window..\n";
//bool s=MoveWindow(windowHandle, 0, 0, 1920, 1080, true);
SetWindowPos(
windowHandle,
HWND_TOP,
0,
0,
600,
600,
SWP_NOSIZE
);
return FALSE; // Stop enumerating windows
}
return TRUE; // Continue enumerating
}
void MoveWindowToFixedLocation(DWORD processId) {
EnumWindows(&EnumWindowsProcBack, (LPARAM)processId);
}
HRESULT LaunchApp(LPCWSTR AUMID, DWORD &pid)
{
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
if (FAILED(hr))
{
wprintf(L"LaunchApp %s: Failed to init COM. hr = 0x%08lx \n", AUMID, hr);
}
{
CComPtr<IApplicationActivationManager> AppActivationMgr = nullptr;
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_ApplicationActivationManager, nullptr,
CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&AppActivationMgr));
if (FAILED(hr))
{
wprintf(L"LaunchApp %s: Failed to create Application Activation Manager.hr = 0x%08lx \n", AUMID, hr);
}
}
if (SUCCEEDED(hr))
{
//DWORD pid = 0;
hr = AppActivationMgr->ActivateApplication(AUMID, nullptr, AO_NONE,
&pid);
if (FAILED(hr))
{
wprintf(L"LaunchApp %s: Failed to Activate App. hr = 0x%08lx \n", AUMID, hr);
}
}
}
CoUninitialize();
return hr;
}
int main() {
DWORD pid = 0;
LaunchApp(L"Microsoft.Windows.HolographicFirstRun_cw5n1h2txyewy!App", pid);
//cout << pid;
MoveWindowToFixedLocation(pid);
}
It's impossible. UWP app runs in own closed environment. A desktop application cannot sent it any signal.

How to apply masking for mouse cursor while writing in to icon(.ico)

I using GetCursorInfo to capture cursor but while saving the cursor as icon getting some black rectangle over on icon.
For windows default cursors are fine but few custom cursor I facing this issue http://www.cursors-4u.com/
Placed one example cursor icon in link https://www.google.com/search?q=cursor+icon&rlz=1C1CHBD_enIN789IN789&source=lnms&tbm=isch&sa=X&ved=0ahUKEwix9aj_gq_iAhWCXCsKHcusD0oQ_AUIDigB&biw=1366&bih=657#imgrc=rOxlbRoBfnKs8M:
HRESULT SaveIcon(HICON hIcon, const char* path)
{
// Create the IPicture intrface
PICTDESC desc = { sizeof(PICTDESC) };
desc.picType = PICTYPE_ICON;
desc.icon.hicon = hIcon;
IPicture* pPicture = 0;
HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)&pPicture);
if (FAILED(hr)) return hr;
// Create a stream and save the image
IStream* pStream = 0;
CreateStreamOnHGlobal(0, TRUE, &pStream);
LONG cbSize = 0;
hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize);
// Write the stream content to the file
if (!FAILED(hr))
{
HGLOBAL hBuf = 0;
GetHGlobalFromStream(pStream, &hBuf);
void* buffer = GlobalLock(hBuf);
HANDLE hFile = CreateFileA(path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (!hFile)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
DWORD written = 0;
WriteFile(hFile, buffer, cbSize, &written, 0);
CloseHandle(hFile);
}
GlobalUnlock(buffer);
}
// Cleanup
pStream->Release();
pPicture->Release();
return hr;
}
//Capture cursor.
CURSORINFO getHCursor()
{
CURSORINFO cursorInfo;
cursorInfo.cbSize = sizeof(CURSORINFO);
if (GetCursorInfo(&cursorInfo) == 0)
{
MessageBox(NULL, _T("Exception : GetCursorInfo creation failed"),_T("message"),MB_OK|MB_SYSTEMMODAL);
cursorInfo.hCursor = NULL;
return cursorInfo;
}
return cursorInfo;
}
//Main Call
int _tmain(int argc, _TCHAR* argv[])
{
while (true)
{
CURSORINFO CursorInfo = getHCursor();
if (CursorInfo.hCursor == NULL)
{
::Sleep(MinSleep);
continue;
}
SaveIcon((HICON)CursorInfo.hCursor, "C:\\Users\\Desktop\\myicon.ico");
Sleep(MaxSleep);
}
return 0;
}
My agenda is to capture cursor and save cursor in to icon(.ico) file or load in to buffer.
Is any other way I can write cursor data in to icon file or buffer ?
The ICONINFO struct contains two members, hbmMask and hbmColor, that contain the mask and color bitmaps, respectively, for the cursor (see the MSDN page for ICONINFO for the official documentation).
When you call GetIconInfo() for the default cursor, the ICONINFO struct contains both valid mask and color bitmaps.
There is probably a better way to render the cursor that the
BitBlt() - BitBlt() - MakeTransparent() combination of method
calls.
Refer to the #Tarsier approach, although it's C #, but the idea is the same.
Link: Capturing the Mouse cursor image

Microsoft SDK AMCap GetCurrentImage error

I am trying to modify the existing AmCap application, available through Microsoft's SDK Direct Show samples, in order to get an image of the captured stream when I press the space button. Below is the point in which I am handling the space keydown.
case WM_KEYDOWN:
if((GetAsyncKeyState(VK_ESCAPE) & 0x01) && gcap.fCapturing)
{
StopCapture();
if(gcap.fWantPreview)
{
BuildPreviewGraph();
StartPreview();
}
}
else if ((GetAsyncKeyState(VK_SPACE) & 0x01))
{
IMediaControl *pMC = NULL;
HRESULT hr = gcap.pFg->QueryInterface(IID_IMediaControl, (void **)&pMC);
if (SUCCEEDED(hr)){
hr=pMC->Pause();
if (SUCCEEDED(hr)){
CaptureImage(TEXT("C:\\output.bmp"));
pMC->Run();
pMC->Release();
}else
ErrMsg(TEXT("Failed to pause stream! hr=0x%x"), hr);
}
else
ErrMsg(TEXT("Cannot grab image"));
}
break;
Below is the contents of the CaptureImage function.
HRESULT hr;
SmartPtr<IBasicVideo> pWC;
// If we got here, gcap.pVW is not NULL
ASSERT(gcap.pVW != NULL);
hr = gcap.pVW->QueryInterface(IID_IBasicVideo, (void**)&pWC);
if (pWC)
{
long bufSize;
long *lpCurrImage = NULL;
pWC->GetCurrentImage(&bufSize, NULL);
lpCurrImage = (long *)malloc(bufSize);
//
// Read the current video frame into a byte buffer. The information
// will be returned in a packed Windows DIB and will be allocated
// by the VMR.
hr = pWC->GetCurrentImage(&bufSize, lpCurrImage);
if (SUCCEEDED(hr))
{
HANDLE fh;
BITMAPFILEHEADER bmphdr;
BITMAPINFOHEADER bmpinfo;
DWORD nWritten;
memset(&bmphdr, 0, sizeof(bmphdr));
memset(&bmpinfo, 0, sizeof(bmpinfo));
bmphdr.bfType = ('M' << 8) | 'B';
bmphdr.bfSize = sizeof(bmphdr) + sizeof(bmpinfo) + bufSize;
bmphdr.bfOffBits = sizeof(bmphdr) + sizeof(bmpinfo);
bmpinfo.biSize = sizeof(bmpinfo);
bmpinfo.biWidth = 640;
bmpinfo.biHeight = 480;
bmpinfo.biPlanes = 1;
bmpinfo.biBitCount = 32;
fh = CreateFile(TEXT("C:\\Users\\mike\\Desktop\\output.bmp"),
GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(fh, &bmphdr, sizeof(bmphdr), &nWritten, NULL);
WriteFile(fh, &bmpinfo, sizeof(bmpinfo), &nWritten, NULL);
WriteFile(fh, lpCurrImage, bufSize, &nWritten, NULL);
CloseHandle(fh);
ErrMsg(TEXT("Captured current image to %s"), szFile);
return TRUE;
}
else
{
ErrMsg(TEXT("Failed to capture image! hr=0x%x"), hr);
return FALSE;
}
}
return FALSE;
The problem is that when I am trying to run the app, I receive an HRESULT (0x8000ffff) error when the GetCurrentImage function is being called.
On the other hand in case I execute the app through the VS debugger the code works just fine.
I tried to add a Sleep just after the stream pMC->Pause(), assuming that the problem was timing issue but that did not work.
Any ideas would be extremely helpful!
Thank you in advance.