After I close the main window of my app, process remains listed in windows task manager's processes list.
Here's the code below, anyone has an idea what to modify to successfully exit process on app exit (or main window close).
int WINAPI WinMain(HINSTANCE inst,HINSTANCE prev,LPSTR cmd,int show)
{
HRESULT hr = CoInitialize(0); MSG msg={0}; DWORD no;
IGraphBuilder* graph= 0; hr = CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&graph );
IMediaControl* ctrl = 0; hr = graph->QueryInterface( IID_IMediaControl, (void **)&ctrl );
ICreateDevEnum* devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
IEnumMoniker* cams = 0; hr = devs?devs->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &cams, 0):0;
IMoniker* mon = 0; hr = cams->Next (1,&mon,0); // get first found capture device (webcam?)
IBaseFilter* cam = 0; hr = mon->BindToObject(0,0,IID_IBaseFilter, (void**)&cam);
hr = graph->AddFilter(cam, L"Capture Source"); // add web cam to graph as source
IEnumPins* pins = 0; hr = cam?cam->EnumPins(&pins):0; // we need output pin to autogenerate rest of the graph
IPin* pin = 0; hr = pins?pins->Next(1,&pin, 0):0; // via graph->Render
hr = graph->Render(pin); // graph builder now builds whole filter chain including MJPG decompression on some webcams
IEnumFilters* fil = 0; hr = graph->EnumFilters(&fil); // from all newly added filters
IBaseFilter* rnd = 0; hr = fil->Next(1,&rnd,0); // we find last one (renderer)
hr = rnd->EnumPins(&pins); // because data we are intersted in are pumped to renderers input pin
hr = pins->Next(1,&pin, 0); // via Receive member of IMemInputPin interface
IMemInputPin* mem = 0; hr = pin->QueryInterface(IID_IMemInputPin,(void**)&mem);
DsHook(mem,6,Receive); // so we redirect it to our own proc to grab image data
hr = ctrl->Run();
while ( GetMessage( &msg, 0, 0, 0 ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
};
Disclaimer: I made no attempt to make this look pretty or do error checking. It works as far as I can tell (when I close the window, the application ends), but it's not exemplary code at all.
The window does not post a WM_QUIT message on its own; you have to do that yourself. You can do it as follows:
Create a window for messages:
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = proc; // function which will handle messages
wx.hInstance = GetModuleHandle(0);
wx.lpszClassName = "some class";
RegisterClassEx(&wx);
HWND hwnd = CreateWindowEx(0, "some class", "some name", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
Make a IMediaEventEx * and use it to direct notifications to the window:
I assume a global IMediaEventEx *event;. Please don't do it the quick dirty way.
graph->QueryInterface(IID_IMediaEventEx, (void **) &event);
event->SetNotifyWindow((OAHWND) hwnd, WM_APP + 1, 0);
Make the window procedure handle the case of the user aborting:
LRESULT CALLBACK proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (msg == WM_APP + 1) {
long evt;
LONG_PTR param1, param2;
while (SUCCEEDED(event->GetEvent(&evt, ¶m1, ¶m2, 0))) {
event->FreeEventParams(evt, param1, param2);
if (evt == EC_USERABORT) {
PostQuitMessage(0);
}
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Related
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.
I would need to get all elements of webpage displayed in IE from a c++ program.
I tried to see with spy++ but there's only the IEFrame.
So I'm thinking about using the developement tool (F12 in IE), I heard there's a way to automat it, a good idea ?
Thanks
You can get an IHtmlDocument2 reference from an IE's window handle, even out-of-process. This is documented here https://support.microsoft.com/en-us/help/249232/how-to-get-ihtmldocument2-from-a-hwnd, but not really supported by Microsoft.
However it looks like it still works today, I've tested it with a Windows 10 box, and IE is now a frozen app, so not going to change any time soon.
Once you have the proper HWND for Internet Explorer, than you can get the DOM with a code like this. Make sure IE and your program run at the same security level
The DOM is the same as when you're coding IE inprocess (host, activex, etc.), however for security reasons, some things may not work :
void DoSomeDomOperations(HWND hwnd)
{
UINT msg = RegisterWindowMessage(L"WM_HTML_GETOBJECT");
LRESULT result = 0;
SendMessageTimeout(hwnd, msg, NULL, NULL, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&result);
if (!result)
return;
// get main document object
IHTMLDocument2 *doc = NULL;
ObjectFromLresult(result, IID_IHTMLDocument2, NULL, (void**)&doc);
if (!doc)
return;
// get document's url
BSTR url = NULL;
doc->get_URL(&url);
wprintf(L"url:%s\n", url);
SysFreeString(url);
// get body element
IHTMLElement *element = NULL;
doc->get_body(&element);
if (element)
{
BSTR text = NULL;
element->get_innerText(&text);
wprintf(L"text:%s\n", text);
SysFreeString(text);
element->Release();
}
// etc.
// etc.
doc->Release();
}
And here is a full sample console app that scans all current IE processes running:
BOOL CALLBACK GetIEServerWindowProc(HWND hwnd, LPARAM lParam)
{
// enumerate all child windows to find IE's COM server
wchar_t className[100];
GetClassName(hwnd, className, 100);
if (!wcscmp(className, L"Internet Explorer_Server"))
{
*((HWND*)lParam) = hwnd;
return FALSE;
}
return TRUE;
}
HWND GetIEServerWindow(HWND hwnd)
{
HWND serverHwnd = NULL;
EnumChildWindows(hwnd, GetIEServerWindowProc, (LPARAM)&serverHwnd);
return serverHwnd;
}
struct IEServer
{
DWORD processId;
HWND serverHwnd;
};
BOOL CALLBACK GetIEProcessServerWindowProc(HWND hwnd, LPARAM lParam)
{
DWORD processId = ((IEServer*)lParam)->processId;
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
if (pid == processId)
{
HWND serverHwnd = GetIEServerWindow(hwnd);
if (serverHwnd)
{
((IEServer*)lParam)->serverHwnd = serverHwnd;
return FALSE;
}
}
return TRUE;
}
HWND GetIEProcessServerWindow(DWORD processId)
{
IEServer ie = { processId, NULL };
EnumWindows(GetIEProcessServerWindowProc, (LPARAM)&ie);
return ie.serverHwnd;
}
void EnumerateIEProcesses()
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (h == INVALID_HANDLE_VALUE)
return;
PROCESSENTRY32 process;
process.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(h, &process))
{
do
{
// we only consider IE processes
if (!wcscmp(process.szExeFile, L"iexplore.exe"))
{
HWND serverHwnd = GetIEProcessServerWindow(process.th32ProcessID);
if (serverHwnd)
{
DoSomeDomOperations(serverHwnd);
}
}
} while (Process32Next(h, &process));
}
CloseHandle(h);
}
int main()
{
CoInitialize(NULL);
EnumerateIEProcesses();
CoUninitialize();
return 0;
}
I am creating a DLL which gets called from a Windows application. It calls my function which then spawns a thread running PttThread shown below. I then register a message only window to handle raw input events. None of the calls return any errors but I do not get raw input events. However, if I add a delay after creating the window but before registering the raw input it suddenly works.
Since Windows does not tell me anything is wrong, how can I change my code so initialisation works properly?
DWORD WINAPI PttThread(LPVOID lpParameter) {
if (!hInstance) {
hInstance = GetModuleHandle(NULL);
}
//Create message only window
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = messageProc;
wx.hInstance = hInstance;
wx.lpszClassName = class_name;
if (!RegisterClassEx(&wx)) {
printf("could not register window class: ");
printLastError();
}
windowHandle = CreateWindowEx(0, class_name, L"R4nd0m_dummy_name", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
if (!windowHandle) {
printf("Could not create window\n");
printLastError();
}
printf("hinstance %u\nhwnd %u\n", hInstance, windowHandle);
// HERE
Sleep(1000); //Then raw input works
// Setup raw input
RAWINPUTDEVICE rid[1];
rid[0].usUsagePage = 0x01;
rid[0].usUsage = 0x06;
rid[0].dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
rid[0].hwndTarget = windowHandle;
if (RegisterRawInputDevices(rid, 1, sizeof(rid[0])) == FALSE) {
printf("!!! Could not setup keyboard input\n");
printLastError();
}
printf("Finish setup of PTT\n");
// Raw input does NOT work if Sleep(1000) is move to here
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
printf("Message received\n"); //Does not print if early registration of raw input.
if (msg.message == MSG_SHUTDOWN) {
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
threadShutdown();
return 0;
}
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.
I need load a video of any file format into a CStatic control for my MFC application I have written the code as I studied from web to load it. The Code snippet is given below. But it doesn't work. Any idea about it?
LRESULT SIMTankConfigureWindowDlg::OnFinishedFrame(WPARAM wParam, LPARAM lParam)
{
HRESULT hr = S_OK;
if(m_bFinishIntroMovie)
{
m_pGraph->play();
}
else
{
//
//SAFE_DELETE(m_pGraph);
m_bFinishIntroMovie = true;
m_staticMovieCanvas.ShowWindow(0);
m_staticMovieCanvas.MoveWindow(310,52, 345, 167);
m_pGraph->setSizeDisplayWindow(CSize(345, 167));
//
CString str;
str = m_strCurrentDirName + "\\" + _T("T-59Tank.mpg");
LPWSTR lpszW = new WCHAR[255];
LPTSTR lpStr = str.GetBuffer( str.GetLength() );
int nLen = MultiByteToWideChar(CP_ACP, 0,lpStr, -1, NULL, NULL);
MultiByteToWideChar(CP_ACP, 0, lpStr, -1, lpszW, nLen);
//
hr = m_pGraph->openFile(lpszW, 0);
if(SUCCEEDED(m_pGraph->play()))
{
//
m_staticMovieCanvas.ShowWindow(1);
}
delete[] lpszW;
}
return hr;
}