18/04/2023 - oregon ha scritto:
L'utilità era riferita a tutto compresa la lettura delle finestre e il rrIavvio nelle stesse posizioni.
Quello che ti serve per fare quello che chiedi sono le api di windows. Enumerazione finestre e processi.il forum non serve a darti del codice. Hai impostato tu uno scheletro di codice su cui lavorare? Mostralo
E intanto leggi
https://devblogs.microsoft.com/oldnewthing/20130318-00/?p=4933
https://stackoverflow.com/questions/131690/how-can-i-programmatically-manipulate-windows-desktop-icon-locations
Il primo Link è molto interessante. Come hai fatto a trovarlo? Non lo ricordo tra le innumerevoli pagine che ho sfogliato.
Il secondo lo avevo visto anche io ma non sono riuscito a sfruttarlo.
Questo è il semplicissimo codice che, catturando istruzioni qua e la, sono riuscito a mettere insieme. Produce semplicemente il risultato di stampare a video i processi attivi di cui posso visualizzare sia il percorso che la finestra principale. Questo listato, se lo si compila funziona. Peccato che non sono riuscito ad avere anche il file che è aperto. Per intenderci C:\Windows\System32\notepad.exe è il programma che ha avviato il processo ma non ho C:\Doc\prova.txt che è il file aperto su notepad.
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace InfoFinestreDesktop2023
{
internal class Program
{
[DllImport("Kernel32.dll")] static extern uint QueryFullProcessImageName(IntPtr hProcess, uint flags, StringBuilder text, out uint size);
[DllImport("user32.dll")] static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);
[DllImport("user32.dll")] static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")] static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")] static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);
[DllImport("user32.dll")] static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
public struct Rect { public int Left { get; set; } public int Top { get; set; } public int Right { get; set; } public int Bottom { get; set; } }
static void Main(string[] args)
{
// ***************** Trovo tutti i processi e seleziono solo quelli che hanno un percorso e una finestra
Process[] processes = Process.GetProcesses(); // tutti i processi in esecuzione
List<Process> ProcessesOK = new List<Process>(); // Lista di processi OK: Con percorso e la finestra principale di riferimento
Console.WriteLine("Numero totale processi: " + processes.Count());
Console.WriteLine("");
foreach (Process proc in processes)
{
if (GetPathToApp(proc) != "" && proc.MainWindowHandle != IntPtr.Zero) // Il Processo deve avere sia il percorso che una finestra principale
{
ProcessesOK.Add(proc);
}
}
Rect rectangle;
foreach (Process proc in ProcessesOK)
{
rectangle = DimWin(proc.MainWindowHandle);
Console.WriteLine("Processo Nome: " + proc + " (ID: " + proc.Id + ")" + " (MainWinH: " + proc.MainWindowHandle + ")");
Console.WriteLine("NomeFinestra: >" + NomeFinestra(proc.MainWindowHandle) + "<");
Console.WriteLine("Posizione <Left(x1), Top(y1), Right(x2), Bottom(y2)>: " + rectangle.Left + ", " + rectangle.Top + ", " + rectangle.Right + ", " + rectangle.Bottom);
Console.WriteLine("Processo Percorso: " + GetPathToApp(proc));
Console.WriteLine("");
}
System.Console.WriteLine("-----------------------------------------------------------------FINE");
Console.ReadLine();
}
public static Rect DimWin(IntPtr handle, int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0)
// Dimensiona la finesta nel desktop
// Se x1=0, int y1=0, int x2 = 0, int y2 = 0 allora non impone nessuna dimensione
// Restituisce sempre un rettangolo con le coordinate della finestra di entrata: prima della eventuale modifica.
// Se sono presenti i valori x1, y1, x2 e y2 allora setta la finestra con questi valori.
{
Rect rettangoloOLD = new Rect();
GetWindowRect(handle, ref rettangoloOLD);
if (!(x1 == 0 & y1 == 0 & x2 == 0 & y2 == 0) & !(y2 <= y1 | x2 <= x1)) // Se si prova a settare la finestra senza una dimensione va in GET
{
// Setto la dimensione della finestra come richiesto
// Rect rettangolo = new Rect();
// rettangolo.Left = x1;
// rettangolo.Top = y1;
// rettangolo.Right = x2;
// rettangolo.Bottom = y2;
SetWindowPos(handle, 0, x1, y1, x2 - x1, y2 - y1, 0x0040);
}
return rettangoloOLD;
}
public static string GetPathToApp(Process proc)
// Restituisce il nome del file eseguibile relativo al processo in input (se non presente stringa vuota)
{
string pathToExe = string.Empty;
if (null != proc)
{
uint nChars = 256;
StringBuilder Buff = new StringBuilder((int)nChars);
uint success = 0;
try { success = QueryFullProcessImageName(proc.Handle, 0, Buff, out nChars); }
catch { }
if (0 != success)
{
pathToExe = Buff.ToString();
}
else
{
int error = Marshal.GetLastWin32Error();
pathToExe = ""; // ("Errore = " + error + " quando si chiama la funzione GetProcessImageFileName");
}
}
return pathToExe;
}
public static String NomeFinestra(IntPtr handle)
// Restrituisce il nome della finestra dell'handle in input.
{
int textLength = GetWindowTextLength(handle);
StringBuilder outText = new StringBuilder(textLength + 1);
int a = GetWindowText(handle, outText, outText.Capacity);
return outText.ToString();
}
}
}
Mi piacerebbe far funzionare anche il codice in C++ del Prof. Raymond Chen https://devblogs.microsoft.com/oldnewthing/20130318-00/?p=4933
Ho provato a compilarlo ma mi da l'errore: “RecalcText: identificatore non dichiarato”.
Ecco il codice che ho copiato e poi compilato:
#include <iostream>
#include <shlwapi.h>
#include <shlobj.h>
#include <exdisp.h>
TCHAR g_szPath[MAX_PATH];
TCHAR g_szItem[MAX_PATH];
int main()
{
std::cout << "Hello World!\n";
}
BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
SetTimer(hwnd, 1, 1000, RecalcText);
return TRUE;
}
void PaintContent(HWND hwnd, PAINTSTRUCT* pps)
{
TextOut(pps->hdc, 0, 0, g_szPath, lstrlen(g_szPath));
TextOut(pps->hdc, 0, 20, g_szItem, lstrlen(g_szItem));
}
void CALLBACK RecalcText(HWND hwnd, UINT, UINT_PTR, DWORD)
{
HWND hwndFind = GetForegroundWindow();
g_szPath[0] = TEXT('\0');
g_szItem[0] = TEXT('\0');
IShellWindows* psw;
if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL,
IID_IShellWindows, (void**)&psw))) {
VARIANT v;
V_VT(&v) = VT_I4;
IDispatch* pdisp;
BOOL fFound = FALSE;
for (V_I4(&v) = 0; !fFound && psw->Item(v, &pdisp) == S_OK;
V_I4(&v)++) {
IWebBrowserApp* pwba;
if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) {
HWND hwndWBA;
if (SUCCEEDED(pwba->get_HWND((LONG_PTR*)&hwndWBA)) &&
hwndWBA == hwndFind) {
fFound = TRUE;
IServiceProvider* psp;
if (SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) {
IShellBrowser* psb;
if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser,
IID_IShellBrowser, (void**)&psb))) {
IShellView* psv;
if (SUCCEEDED(psb->QueryActiveShellView(&psv))) {
IFolderView* pfv;
if (SUCCEEDED(psv->QueryInterface(IID_IFolderView,
(void**)&pfv))) {
IPersistFolder2* ppf2;
if (SUCCEEDED(pfv->GetFolder(IID_IPersistFolder2,
(void**)&ppf2))) {
LPITEMIDLIST pidlFolder;
if (SUCCEEDED(ppf2->GetCurFolder(&pidlFolder))) {
if (!SHGetPathFromIDList(pidlFolder, g_szPath)) {
lstrcpyn(g_szPath, TEXT("<not a directory>"), MAX_PATH);
}
int iFocus;
if (SUCCEEDED(pfv->GetFocusedItem(&iFocus))) {
LPITEMIDLIST pidlItem;
if (SUCCEEDED(pfv->Item(iFocus, &pidlItem))) {
IShellFolder* psf;
if (SUCCEEDED(ppf2->QueryInterface(IID_IShellFolder,
(void**)&psf))) {
STRRET str;
if (SUCCEEDED(psf->GetDisplayNameOf(pidlItem,
SHGDN_INFOLDER,
&str))) {
StrRetToBuf(&str, pidlItem, g_szItem, MAX_PATH);
}
psf->Release();
}
CoTaskMemFree(pidlItem);
}
}
CoTaskMemFree(pidlFolder);
}
ppf2->Release();
}
pfv->Release();
}
psv->Release();
}
psb->Release();
}
psp->Release();
}
}
pwba->Release();
}
pdisp->Release();
}
psw->Release();
}
InvalidateRect(hwnd, NULL, TRUE);
}
E' un codice con molti riferimenti a puntatori che per mia ignoranza mal digerisco. Comunque se funzionasse potrei andare a tentativi e rendermelo fruibile.
Sai darmi un'indicazione di come poterlo vedere funzionare? Io uso Visual Studio 2022.