Ok, this probably has a really simple answer, but I've never tried to do it before: How do you launch a web page from within an app? You know, "click here to go to our FAQ", and when they do it launches their default web browser and goes to your page. I'm working in C/C++ in Windows, but if there's a broader, more portable way to do it I'd like to know that, too.
#include <windows.h>
void main()
{
ShellExecute(NULL, "open", "http://yourwebpage.com",
NULL, NULL, SW_SHOWNORMAL);
}
I believe you want to use the ShellExecute() function which should respect the users choice of default browser.
Please read the docs for ShellExecute closely. To really bulletproof your code, they recommend initializing COM. See the docs here, and look for the part that says "COM should be initialized as shown here". The short answer is to do this (if you haven't already init'd COM):
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)
For the record (since you asked for a cross-platform option), the following works well in Linux:
#include <unistd.h>
#include <stdlib.h>
void launch(const std::string &url)
{
std::string browser = getenv("BROWSER");
if(browser == "") return;
char *args[3];
args[0] = (char*)browser.c_str();
args[1] = (char*)url.c_str();
args[2] = 0;
pid_t pid = fork();
if(!pid)
execvp(browser.c_str(), args);
}
Use as:
launch("http://example.com");
You can use ShellExecute function.
Sample code:
ShellExecute( NULL, "open", "http://stackoverflow.com", "", ".", SW_SHOWDEFAULT );
For some reason, ShellExecute do not work sometimes if application is about to terminate right after call it. We've added Sleep(5000) after ShellExecute and it helps.
Related
The following sample has reliably returned the name of the process that is associated with the active window, but does not work with the newer modern/universal apps because it returns the name of a helper process WWAHost.exe on Windows 8 and ApplicationFrameHost.exe on Windows 10 rather than the name of the app.
HWND active_window = GetForegroundWindow();
GetWindowThreadProcessId(active_window, &active_process_id);
HANDLE active_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, active_process_id);
GetProcessImageFileName(active_process, image_name, 512);
With Windows 10 the ApplicationFrameHost.exe is the process that creates the window handles and is what gets returned by GetWindowThreadProcessId(), is there another Win32 API that can be used to get the active process of universal app that is active?
Also tried using GetApplicationUserModelId() and GetPackageFullName() with no success as they return APPMODEL_ERROR_NO_APPLICATION and APPMODEL_ERROR_NO_PACKAGE respectively because the active_process handle is just the helper process and not the process of the active application.
Any other APIs to use to get the process name of a Modern/Universal application given the hwnd of the window, or otherwise figure out the process name of the universal app is active.
Thanks in advance!
Be sure to use the Spy++ utility when you want to reverse-engineer something like this. Included with Visual Studio, you need the 64-bit version in Common7\Tools\spyxx_amd64.exe. Use Search > Find Window and drag the bullseye to a UWP app, like Weather.
You'll see the window you'll find with GetForegroundWindow(), it has at least 3 child windows:
ApplicationFrameTitleBarWindow
ApplicationFrameInputSinkWindow
Windows.Core.UI.CoreWindow, that's the host window for the UWP app and the one you are interested in. Right-click it and select Properties, Process tab, click the Process ID. That takes you to the real owner process you want to know.
So you just need to make an extra step from the code you already have, you just have to enumerate the child windows and look for one with a different owner process. Some C code, trying to make it as universal as possible without making too many assumptions and not enough error checking:
#include <stdio.h>
#include <Windows.h>
typedef struct {
DWORD ownerpid;
DWORD childpid;
} windowinfo;
BOOL CALLBACK EnumChildWindowsCallback(HWND hWnd, LPARAM lp) {
windowinfo* info = (windowinfo*)lp;
DWORD pid = 0;
GetWindowThreadProcessId(hWnd, &pid);
if (pid != info->ownerpid) info->childpid = pid;
return TRUE;
}
int main()
{
Sleep(2000);
HWND active_window = GetForegroundWindow();
windowinfo info = { 0 };
GetWindowThreadProcessId(active_window, &info.ownerpid);
info.childpid = info.ownerpid;
EnumChildWindows(active_window, EnumChildWindowsCallback, (LPARAM)&info);
HANDLE active_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, info.childpid);
WCHAR image_name[MAX_PATH] = { 0 };
DWORD bufsize = MAX_PATH;
QueryFullProcessImageName(active_process, 0, image_name, &bufsize);
wprintf(L"%s\n", image_name);
CloseHandle(active_process);
return 0;
}
Output on the Weather program:
C:\Program Files\WindowsApps\Microsoft.BingWeather_4.5.168.0_x86__8wekyb3d8bbwe\
Microsoft.Msn.Weather.exe
Here is a small console app application that continuously (so you can test it easily selecting different windows on your desktop) display information about the current foreground window process and store process, if any.
Apps can have a window hierarchy that can span multiple processes. What I do here is search the first sub window that has the 'Windows.UI.Core.CoreWindow' class name.
This app uses the UIAutomation API (and also smart pointers, smart BSTRs and smart VARIANTs provided by the #import directive). I suppose you can do the same with standard Windows SDK, but I find the UIAutomation used this way quite elegant.
#include "stdafx.h"
#import "UIAutomationCore.dll"
using namespace UIAutomationClient;
int main()
{
// initialize COM, needed for UIA
CoInitialize(NULL);
// initialize main UIA class
IUIAutomationPtr pUIA(__uuidof(CUIAutomation));
do
{
// get the Automation element for the foreground window
IUIAutomationElementPtr foregroundWindow = pUIA->ElementFromHandle(GetForegroundWindow());
wprintf(L"pid:%i\n", foregroundWindow->CurrentProcessId);
// prepare a [class name = 'Windows.UI.Core.CoreWindow'] condition
_variant_t prop = L"Windows.UI.Core.CoreWindow";
IUIAutomationConditionPtr condition = pUIA->CreatePropertyCondition(UIA_ClassNamePropertyId, prop);
// get the first element (window hopefully) that satisfies this condition
IUIAutomationElementPtr coreWindow = foregroundWindow->FindFirst(TreeScope::TreeScope_Children, condition);
if (coreWindow)
{
// get the process id property for that window
wprintf(L"store pid:%i\n", coreWindow->CurrentProcessId);
}
Sleep(1000);
} while (TRUE);
cleanup:
CoUninitialize();
return 0;
}
Does taking snapshot of running processes and pulling the name out of it by comparing process id not work?
Full reference here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686837(v=vs.85).aspx
But you fix the snapshot with CreateToolhelp32Snapshot().
Or from WTSEnumerateProcesses() and surrounding API?
Pretty sure it worked in Win 8. Is it broken in 10?
Starting from Win10 Anniversary Update ApplicationFrameHost child window return anything but UWP application. It worked only in Tablet mode after relogon.
case WM_CREATE:
{
int randomsize=0;
//std::string lineofquote;
char lineofquote[255];
std::ifstream infile;
infile.open("quotes.txt",std::ios::in);
if (infile)
{
MessageBox(NULL,"infile failed","Error reading file", MB_OK);
return 0;
}
newhandler = CreateWindow(TEXT("static"),TEXT("Quote here") ,WS_CHILD | WS_VISIBLE , 0,0,550,150,hWnd,NULL,NULL,NULL);
while(!infile.eof())//get file size
{
infile.getline(lineofquote,255,'\n');
SetWindowText(newhandler,lineofquote);
randomsize++;
}
infile.close();
//std::cout<<randomsize;
break;
}
When i run this program, i dont seem to see my windows at all. What might be the problem here?
That is not the way you create a window. You create a window using CreateWindow API. There are a couple of things you need to do along with it. May be this MSDN tutorial can help.
WM_CREATE is an event fired when a window is created, typically using the above API.
Always read the documentation properly. As long as you are dealing with Win32 APIs, MSDN will be your bible.
Check your ShowWindow() function. You could set CmdShow parameter to 0 which means that your window will not be visible, or just simply you forgot to call this function. Also, you could check if RegisterClassEx(...) worked propely.
I am designing a system where the user makes a gesture, then my program captures it (using a web cam) and my program looks in a rule system (based on XML) which are the actions that it has to do.
Ok, once I have explained the background, I'd like to know how I could make my program "execute" the Show Desktop button. I'd like to provide the user the possibility to do a gesture and show the desktop. Is it possible? I have been looking the program (.exe) that executes the Show Desktop button and I am afraid that does not exist.
From this MSDN blog post (dated 2004 but surely still valid), you must call ToggleDesktop().
in C#:
// Create an instance of the shell class
Shell32.ShellClass objShel = new Shell32.ShellClass();
// Show the desktop
((Shell32.IShellDispatch4) objShel).ToggleDesktop();
// Restore the desktop
((Shell32.IShellDispatch4) objShel).ToggleDesktop();
EDIT
C++ version:
#include <Shldisp.h>
CoInitialize(NULL);
// Create an instance of the shell class
IShellDispatch4 *pShellDisp = NULL;
HRESULT sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp );
// Show the desktop
sc = pShellDisp->ToggleDesktop();
// Restore the desktop
sc = pShellDisp->ToggleDesktop();
pShellDisp->Release();
From http://www.codeguru.com/forum/showthread.php?t=310202:
#define MIN_ALL 419
#define MIN_ALL_UNDO 416
int main(int argc, char* argv[])
{
HWND lHwnd = FindWindow("Shell_TrayWnd",NULL);
SendMessage(lHwnd,WM_COMMAND,MIN_ALL,0); // Minimize all windows
Sleep(2000);
SendMessage(lHwnd,WM_COMMAND,MIN_ALL_UNDO,0); // Bring all back up again.
return 0;
}
Hope it helps. It at least does what it should, minimizes all the windows aka. shows desktop.
You need to call ToggleDesktop.
In Windows you can copy the script:
[Shell]
Command=2
IconFile=explorer.exe,3
[Taskbar]
Command=ToggleDesktop
into a file "somefile.scf" and invoke it from the shell by executing "somefile.scf" by hand. This is also possible with C++.
How to set the console window title in C?
printf("%c]0;%s%c", '\033', "My Console Title", '\007');
This works only under linux, not in windows.
Does anybody know a "cross-platform" solution? (of course not system ( title=blah ))
windows.h defines SetConsoleTitle().
You could use that everywhere, and declare your own function for linux platforms that does the same thing.
Sounds similar to this posting: (Which is for Java, but the accepted answer uses JNI [ie a C Native call].
How to change command prompt (console) window title from command line Java app?
You can do this by calling SetConsoleTitle.
Maybe you have to implement a "cross-playform" solution yourself.
For windows 2000+, you can use SetConsoleTitle(), more imformation can be found on MSDN.
The most easy way to achieve this in C is to use windows.h header and use the SetConsoleTitle function
Simple Script
#include <stdio.h>
#include <windows.h>
#include <conio.h>
int main()
{
HANDLE handleConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTitle("Mini Desktop App"); // Here add the title of the window
while(1){
printf("Works as expected\n");
printf("Press any Key to exit :)\n");
getch();
break;
}
return 0;
}
Obviously this is trivial to do with win32 api - CreateDirectory(). But I'm trying to host an IShellView, and would like to do this the most shell-oriented way. I would have thought that there would be a createobject or createfolder or some such from an IShellFolder. But neither IShellView nor IShellFolder nor even IFolderView seem to have anything quite like this.
Is there a Shell-programming way to create a new folder? Or do I need to create a folder using a pathname, the old-fashioned way?
If I have to do it via CreateDirectory(), then my next question might be: any ideas as to how to get the IShellView / IFolderView to actually see this new object and display it to the user?
Motivation: Creating my own File Dialog replacement and I want to provide the "new folder" toolbar icon functionality of the standard XP-style file dialog.
EDIT: I went ahead and created something that basically works, using CreateDirectory. However, I'm still hoping that there's a better way to do this, but so that you can see how that works, and to offer better ideas as to solve this issue better:
PidlUtils::Pidl pidl(m_folder);
CFilename folderName(GetDisplayNameOf(pidl), "New Folder");
for (int i = 2; folderName.Exists(); ++i)
folderName.SetFullName(FString("New Folder (%d)", i));
if (!CPathname::Create(folderName, false))
throw CContextException("Unable to create a new folder here: ");
// get the PIDL for the newly created folder
PidlUtils::Pidl pidlNew;
#ifdef UNICODE
const wchar_t * wszName = folderName.c_str();
#else
wchar_t wszName[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, folderName.GetFullName(), -1, wszName, MAX_PATH);
#endif
m_hresult = m_folder->ParseDisplayName(NULL, NULL, wszName, NULL, pidlNew, NULL);
if (FAILED(m_hresult))
throw CLabeledException(FString("Unable to get the PIDL for the new folder: 0x%X", m_hresult));
// upgrade our interface so we can select & rename it
CComQIPtr<IShellView2> sv2(m_shell_view);
if (!sv2)
throw CLabeledException("Unable to obtain the IShellView2 we need to rename the newly created folder.");
// force it to see thew new folder
sv2->Refresh();
// select the new folder, and begin the rename process
m_hresult = sv2->SelectAndPositionItem(pidlNew, SVSI_EDIT|SVSI_DESELECTOTHERS|SVSI_ENSUREVISIBLE|SVSI_POSITIONITEM, NULL);
if (FAILED(m_hresult))
throw CLabeledException(FString("Unable to select and position the new folder item: 0x%X", m_hresult));
Yes, you can get IContextMenu and look for sub menus, but why bother, just call SHChangeNotify after you call CreateDirectory
Shell folders usually implement the IStorage interface, so this is pretty simple. For example, the following creates a folder named "abcd" on the desktop:
CComPtr<IShellFolder> pDesktop;
HRESULT hr = SHGetDesktopFolder(&pDesktop);
if (FAILED(hr)) return;
CComQIPtr<IStorage> pStorage(pDesktop);
if (!pStorage) return;
CComPtr<IStorage> dummy;
hr = pStorage->CreateStorage(L"abcd", STGM_FAILIFTHERE, 0, 0, &dummy);
The Win32 API function CreateDirectory seems to be the "correct way". At least, I can find nothing better - and the answers here don't really shed any light on a better way to do it.