How can I show a window with the a name given as parameter in Windows in C++ - c++

I would like to make my software usable for Linux and Windows (Linux already works). Now I still need some functions so I can run the software on Windows, too.
I am currently trying to use the EnumWindows() function to get the window names and then show the window in the foreground (which matches the parameter).
static BOOL CALLBACK setWindowFocus(HWND hWnd, LPARAM lparam) {
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
// Check if it is the right Windowshandle
if ( windowTitle.compare(programname) == 0 ) <-- programname is a static variable
{
// Set application to the foreground
SetForegroundWindow(hWnd);
}
}
return TRUE;
}
Additionally, I used this to create the variable:
std::string programname;
And this to call it:
static void setWindowFocus(std::string programname)
{
std::cout << "Setting focus to window." << std::endl;
tempsavedProgramname=programname;
EnumWindows(setWindowFocus, NULL);
}
That is working, as long as it is in main(). But, I would like to have it in an extra class with some other functions (I would like to remove the static variable too, if possible).
Is there a way I can use the EnumWindows() function with an anonymous function, or something?
Can I use something like this to pass a string to the function:
EnumWindows(setWindowFocus, reinterpret_cast<LPARAM>(stringvariable));
Or, are there other ways which I can try to reach my goal?
Includes which I used for the code:
Windows.h
winuser.h
string
iostream
I hope that I did not forgot one.

Yes, you can use the LPARAM to pass a string variable into your callback, eg:
static BOOL CALLBACK setWindowFocus(HWND hWnd, LPARAM lparam) {
std::string &programname = *reinterpret_cast<std::string*>(lparam);
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
delete[] buffer; // <-- ADD THIS!
/* I would use this instead:
int length = GetWindowTextLength(hWnd);
std::string windowTitle(length+1, '\0');
windowTitle.resize(GetWindowText(hWnd, &windowTitle[0], length + 1));
*/
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && (length != 0)) {
// Check if it is the right Windowshandle
if (windowTitle == programname)
{
// Set application to the foreground
SetForegroundWindow(hWnd);
return FALSE;
}
}
return TRUE;
}
static void setWindowFocus(std::string programname)
{
std::cout << "Setting focus to window." << std::endl;
EnumWindows(setWindowFocus, reinterpret_cast<LPARAM>(&programname));
}
And yes, you can use a C++11 lambda for the callback, rather than a static class method, but only if you use a non-capturing lambda, which is implicitly convertible to a function pointer (capturing lambdas are not). Fortunately, the LPARAM makes that a possibility, eg:
static void setWindowFocus(std::string programname)
{
std::cout << "Setting focus to window." << std::endl;
EnumWindows(
[](HWND hWnd, LPARAM lparam) -> BOOL {
std::string &programname = *reinterpret_cast<std::string*>(lparam);
// ...
},
reinterpret_cast<LPARAM>(&programname)
);
}
Now, that being said, there is a much simpler solution - since you already know the exact window text you are looking for, you can use FindWindow() instead of EnumWindows(), eg:
static void setWindowFocus(std::string programname)
{
std::cout << "Setting focus to window." << std::endl;
HWND hWnd = FindWindowA(NULL, programname.c_str());
if (hWnd != NULL) {
// Set application to the foreground
SetForegroundWindow(hWnd);
}
}

Here's the callback wrapped up in a class
class enum_windows {
protected:
virtual BOOL call_back(HWND hwnd) {
// Your code here
return TRUE;
}
public:
void start() {
EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL {
enum_windows * obj = reinterpret_cast<enum_windows *>(lParam);
return obj->call_back(hwnd);
}, reinterpret_cast<LPARAM>(this));
}
};
(You've already accepted an answer - I'm a slow typer 😄). I'll leave this here anyway.

Related

C++ Can someone show me how to create a select folder dialog with the Windows API GUi [duplicate]

How to select an existing folder (or create new) from a native Win32 application?
Here is a similar question. It has a good answer for C#/.NET. But I want the same thing for native Win32.
Anybody knows a solution, free code, etc?
Update:
I tried the function from the answer. Everything worked as expected, except it is necessary to call the SHGetPathFromIDList function to retrieve the name of selected directory. Here is a sample screen shot:
SHBrowseForFolder
Do your users a favor, and set at least the BIF_NEWDIALOGSTYLE flag.
To set the initial folder, add the following code:
static int CALLBACK BrowseFolderCallback(
HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
if (uMsg == BFFM_INITIALIZED) {
LPCTSTR path = reinterpret_cast<LPCTSTR>(lpData);
::SendMessage(hwnd, BFFM_SETSELECTION, true, (LPARAM) path);
}
return 0;
}
// ...
BROWSEINFO binf = { 0 };
...
binf.lParam = reinterpret_cast<LPARAM>(initial_path_as_lpctstr);
binf.lpfn = BrowseFolderCallback;
...
and provide a suitable path (such as remembering the last selection, your applications data folder, or similar)
Just as a go to for future users, this article helped me a lot with getting a directory dialog in C++
http://www.codeproject.com/Articles/2604/Browse-Folder-dialog-search-folder-and-all-sub-fol
Here is my code (heavily based/taken on the article)
NOTE: You should be able to copy/paste this into a file / compile it (g++, see VS in ninja edit below) and it'll work.
#include <windows.h>
#include <string>
#include <shlobj.h>
#include <iostream>
#include <sstream>
static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg, LPARAM lParam, LPARAM lpData)
{
if(uMsg == BFFM_INITIALIZED)
{
std::string tmp = (const char *) lpData;
std::cout << "path: " << tmp << std::endl;
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
}
return 0;
}
std::string BrowseFolder(std::string saved_path)
{
TCHAR path[MAX_PATH];
const char * path_param = saved_path.c_str();
BROWSEINFO bi = { 0 };
bi.lpszTitle = ("Browse for folder...");
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
bi.lpfn = BrowseCallbackProc;
bi.lParam = (LPARAM) path_param;
LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );
if ( pidl != 0 )
{
//get the name of the folder and put it in path
SHGetPathFromIDList ( pidl, path );
//free memory used
IMalloc * imalloc = 0;
if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
{
imalloc->Free ( pidl );
imalloc->Release ( );
}
return path;
}
return "";
}
int main(int argc, const char *argv[])
{
std::string path = BrowseFolder(argv[1]);
std::cout << path << std::endl;
return 0;
}
EDIT: I've updated the code to show people how to remember the last selected path and use that.
Also, for VS, using Unicode character set. replace this line:
const char * path_param = saved_path.c_str();
With this:
std::wstring wsaved_path(saved_path.begin(),saved_path.end());
const wchar_t * path_param = wsaved_path.c_str();
My Test code above is compiled with g++, but doing this fixed it in VS for me.
For Windows Vista and above, it's best to use IFileOpenDialog with the FOS_PICKFOLDERS option for a proper open dialog rather than this tree dialog. See Common Item Dialog on MSDN for more details.

C++ Get Another Windows Hwnd In Same Process

I've made a dll that you can inject into applications. I want that dll to find another window in the same process.
Here you can see a example. The console host (KonsolfönstervÀrd) is the dll I injected and I want that to find the lockdown-example window hwnd.
It is very simple to get the handle with the window title. But I don't want to hardcode it for just that application.
HWND parentHandle = FindWindowA(NULL, "Lockdown Example");
I have also tried some stuff with EnumWindows which basically prints all visible windows and their window title. And in the output of that you can see the "Lockdown Example" window.
10828: TheDll
388: Lockdown Example
13380: Microsoft Store
6664: Program Manager
How would I make it only do something when it found the "Lockdown Example" without just giving it a hardcoded title. Instead giving it something like GetCurrentProcessId()
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
//GetWindowThreadProcessId();
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
cout << GetWindowThreadProcessId(hWnd, NULL) << ": " << windowTitle << endl;
}
return TRUE;
}
EnumWindows(enumWindowCallback, NULL)
So I came up to a answer with modifying the enumWindowCallback a little bit.
BOOL CALLBACK enumWindowCallback(HWND hwnd, LPARAM lParam)
{
int length = GetWindowTextLength(hwnd);
char* buffer = new char[length + 1];
GetWindowText(hwnd, buffer, length + 1);
std::string windowTitle(buffer);
DWORD lpdwProcessId;
GetWindowThreadProcessId(hwnd, &lpdwProcessId);
// 1. Checks if the current process is not equals to the value given in the lParam
// 2. Check if the current window is visible
// 3. Check if its not a empty name
// 4. Check so it is not the console window
// All these filters result in to only show all visible windows in the process
// Which in my case is "17260 | 15800: Lockdown Example"
if (lpdwProcessId == lParam && IsWindowVisible(hwnd) && length != 0
&& GetWindowThreadProcessId(GetConsoleWindow(), NULL) != GetWindowThreadProcessId(hwnd, NULL))
{
// Here you can do anything with the window handle (hwnd)
cout << lpdwProcessId << " | "<< GetWindowThreadProcessId(hwnd, NULL) << ": " << windowTitle << endl;
}
return TRUE;
}
Called it with:
EnumWindows(enumWindowCallback, GetCurrentProcessId()); // iterate over all windows

Getting a list of all open windows in c++ and storing them

I'm currently trying to get a list of all opened windows and storing them inside a vector. I've been looking at the code so much that the solution could be very easy but I don't seem to get it done without a global variable (which I want to avoid).
Here is the code:
#include "stdafx.h"
#include "json.h"
#include <algorithm>
using namespace std;
vector<string> vec;
BOOL CALLBACK speichereFenster(HWND hwnd, LPARAM substring){
const DWORD TITLE_SIZE = 1024;
TCHAR windowTitle[TITLE_SIZE];
GetWindowText(hwnd, windowTitle, TITLE_SIZE);
int length = ::GetWindowTextLength(hwnd);
wstring temp(&windowTitle[0]);
string title(temp.begin(), temp.end());
if (!IsWindowVisible(hwnd) || length == 0 || title == "Program Manager") {
return TRUE;
}
vec.push_back(title);
return TRUE;
}
int main() {
EnumWindows(speichereFenster, NULL);
cin.get();
return 0;
}
I want to store all titles in the vector but I don't know how as I can't pass the vector into the function...
Thanks!!!
The second parameter (lParam) to EnumWindows is documented as:
An application-defined value to be passed to the callback function.
Just pass your container to the API call:
int main() {
std::vector<std::wstring> titles;
EnumWindows(speichereFenster, reinterpret_cast<LPARAM>(&titles));
// At this point, titles if fully populated and could be displayed, e.g.:
for ( const auto& title : titles )
std::wcout << L"Title: " << title << std::endl;
cin.get();
return 0;
}
And use it in your callback:
BOOL CALLBACK speichereFenster(HWND hwnd, LPARAM lParam){
const DWORD TITLE_SIZE = 1024;
WCHAR windowTitle[TITLE_SIZE];
GetWindowTextW(hwnd, windowTitle, TITLE_SIZE);
int length = ::GetWindowTextLength(hwnd);
wstring title(&windowTitle[0]);
if (!IsWindowVisible(hwnd) || length == 0 || title == L"Program Manager") {
return TRUE;
}
// Retrieve the pointer passed into this callback, and re-'type' it.
// The only way for a C API to pass arbitrary data is by means of a void*.
std::vector<std::wstring>& titles =
*reinterpret_cast<std::vector<std::wstring>*>(lParam);
titles.push_back(title);
return TRUE;
}
Notes:
The code presented uses a std::wstring in place of std::string. This is necessary so that the entire character set can be represented.
As written, the code isn't correct. There are (invisible) code paths, that have no well-defined meaning. The Windows API is strictly exposed as a C interface. As such, it doesn't understand C++ exceptions. Particularly with callbacks it is vital to never let C++ exceptions travel across unknown stack frames. To fix the code apply the following changes:
[C++11 only] Mark the callback noexcept.
Wrap the entire callback inside a try-catch block, and handle any exceptions appropriately.
[C++11 only] With C++11 you can pass C++ exceptions across unknown stack frames, by passing a std::exception_ptr, and calling std::rethrow_exception at the call site.
Simple code to get all visible windows with non empty title
for (HWND hwnd = GetTopWindow(NULL); hwnd != NULL; hwnd = GetNextWindow(hwnd, GW_HWNDNEXT))
{
if (!IsWindowVisible(hwnd))
continue;
int length = GetWindowTextLength(hwnd);
if (length == 0)
continue;
char* title = new char[length+1];
GetWindowText(hwnd, title, length+1);
if (title == "Program Manager")
continue;
std::cout << "HWND: " << hwnd << " Title: " << title << std::endl;
}

reading from ComboBox

how can i read the text of a selected value of a comboBox in windows aplication(borland C++) for example:
i have combobox which contains 2 values (sum and mult) i want to see if it is sum i have to add the numbers and if it mult i have to multiplicate the numbers so how can i read the value of combobox in this case.
For Windows:
In your window procedure use the WM_COMMAND message and then check for a CBN_SELCHANGE notification. Then use WM_GETTEXT along with WM_GETTEXTLENGTH to receive the selected text like Mark Ingram says. Or you can also use CB_GETCURSEL to receive the identifier of the selected item.
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDC_COMBO:
if (HIWORD(wParam) == CBN_SELCHANGE) {
HWND hCtl = GetDlgItem(hWnd, IDC_COMBO);//Get handle for HMENU item
if (SendMessage(hCtl, CB_GETCURSEL, 0, 0) == compareValue) {
//...
}
}
break;
}
break;
//...
}
}
Assuming that you are using Windows, you can use the following messages:
WM_GETTEXTLENGTH and WM_GETTEXT.
Firstly, get the length of the selected text, then allocate your buffer to ensure it's large enough, then retrieve the actual text. Easy.
Example:
const UINT length = ::SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0);
LPTSTR pszText = new TCHAR[length + 1];
::SendMessage(hWnd, WM_GETTEXT, length + 1, pszText);
// pszText will now contain the text you want, do what you want with it
delete[] pszText; // Remember to delete else you will leak.
I never work with c++ with winapplication but i tried it with the c# and hopefully that you want the desired output as i got through your question if it is not right then you should edit your question.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.Text == "ADD")
{
int a = 12, b = 13, c;
c = a + b;
MessageBox.Show("Result of adding= " + c);
}
else if (comboBox1.Text == "Multiple")
{
int x = 3, y = 5, z;
z = x * y;
MessageBox.Show("Result of multiplication= " + z);
}
}

How to find whether system has the font I needed in MFC?

I want to write the following function
bool IsFontExistInSystem(const CString& fontStyle) const
{
}
Is there any API in windows to do this?
Many Thanks!
Here's some old code I dug out that will check if a font is installed. It could do with being tidied up but you get the idea:
static int CALLBACK CFontHelper::EnumFontFamExProc(ENUMLOGFONTEX* /*lpelfe*/, NEWTEXTMETRICEX* /*lpntme*/, int /*FontType*/, LPARAM lParam)
{
LPARAM* l = (LPARAM*)lParam;
*l = TRUE;
return TRUE;
}
bool Font::IsInstalled(LPCTSTR lpszFont)
{
// Get the screen DC
CDC dc;
if (!dc.CreateCompatibleDC(NULL))
{
return false;
}
LOGFONT lf = { 0 };
// Any character set will do
lf.lfCharSet = DEFAULT_CHARSET;
// Set the facename to check for
_tcscpy(lf.lfFaceName, lpszFont);
LPARAM lParam = 0;
// Enumerate fonts
::EnumFontFamiliesEx(dc.GetSafeHdc(), &lf, (FONTENUMPROC)EnumFontFamExProc, (LPARAM)&lParam, 0);
return lParam ? true : false;
}
You could use EnumFontFamiliesEx to find whether exist actual font.
UPD: I've just learned that it is recommended by MS to use EnumFontFamiliesEx instead of EnumFontFamilies.