मैंने फोरग्राउंड या शीर्षतम खिड़की की जानकारी पढ़ने के लिए थोड़ी देर पहले एक छोटी लाइब्रेरी लिखी, मुख्य रूप से खिड़की का शीर्षक, विंडोज़, मैक ओएस एक्स और लिनक्स में। आप यहाँ स्रोत कोड पा सकते हैं: https://github.com/pcmantinker/Qt-Window-Title-Reader
मैं लिनक्स के लिए विंडोज के लिए देशी विंडोज एपीआई का उपयोग, X11 पुस्तकालयों, और मैक ओएस एक्स पर कोको
यहाँ कैसे सक्रिय विंडो पाने के लिए की एक छोटा सा नमूना है मैक ओएस एक्स में उद्देश्य सी का उपयोग कर ++:
Mac.h
/*
Mac/Cocoa specific code for obtaining information about the frontmost window
*/
#ifndef MAC_H
#define MAC_H
#include <QtCore>
#include "windowinfo.h"
class Mac {
public:
Mac();
QList<WindowInfo> getActiveWindows();
};
#endif // MAC_H
Mac.mm
/*
Mac/Cocoa specific code for obtaining information about the frontmost window
*/
#include "mac.h"
#include "Cocoa/Cocoa.h"
Mac::Mac()
{
}
QList<WindowInfo> Mac::getActiveWindows()
{
QList<WindowInfo> windowTitles;
// get frontmost process for currently active application
ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
NSString *pname = (NSString *)processName;
// loop through all application windows
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
for (NSMutableDictionary* entry in (NSArray*)windowList)
{
NSString* ownerName = [entry objectForKey:(id)kCGWindowOwnerName];
NSString *name = [entry objectForKey:@"kCGWindowName" ];
NSInteger ownerPID = [[entry objectForKey:(id)kCGWindowOwnerPID] integerValue];
NSInteger layer = [[entry objectForKey:@"kCGWindowLayer"] integerValue];
if(layer == 0)
{
if([ownerName isEqualToString:pname])
{
NSRange range;
range.location = 0;
range.length = [ownerName length];
unichar *chars = new unichar[range.length];
[ownerName getCharacters:chars range:range];
QString owner = QString::fromUtf16(chars, range.length);
range.length = [name length];
chars = new unichar[range.length];
[name getCharacters:chars range:range];
QString windowTitle = QString::fromUtf16(chars, range.length);
delete[] chars;
long pid = (long)ownerPID;
WindowInfo wi;
wi.setProcessName(owner);
wi.setWindowTitle(windowTitle);
wi.setPID(pid);
windowTitles.append(wi);
}
}
}
CFRelease(windowList);
CFRelease(processName);
return windowTitles;
}
कृपया ध्यान दें कि कोको में, केवल शीर्षतम विंडो प्राप्त करने का कोई सीधा तरीका नहीं है। आप जो चाहते हैं उसे ढूंढने के लिए आप उनके माध्यम से खिड़कियों और लूप का संग्रह प्राप्त करते हैं।
win.h
/*
Windows API specific code for obtaining information about the frontmost window
*/
#ifndef WIN_H
#define WIN_H
#include <QtCore>
#include "qt_windows.h"
#include "psapi.h"
#include "windowinfo.h"
class win : public QObject
{
Q_OBJECT
public:
win();
QList<WindowInfo> getActiveWindows();
private:
TCHAR buf[255];
};
#endif // WIN_H
win.cpp
#include "win.h"
win::win()
{
}
QList<WindowInfo> win::getActiveWindows()
{
QList<WindowInfo> windowTitles;
HWND foregroundWindow = GetForegroundWindow();
DWORD* processID = new DWORD;
GetWindowText(foregroundWindow, buf, 255);
GetWindowThreadProcessId(foregroundWindow, processID);
DWORD p = *processID;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, p);
TCHAR szProcessName[MAX_PATH];
if (NULL != hProcess)
{
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),
&cbNeeded))
{
GetModuleBaseName(hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR));
}
}
CloseHandle(hProcess);
long pid = (long)p;
QString windowTitle, processName;
#ifdef UNICODE
windowTitle = QString::fromUtf16((ushort*)buf);
processName = QString::fromUtf16((ushort*)szProcessName);
#else
windowTitle = QString::fromLocal8Bit(buf);
processName = QString::fromLocal8Bit(szProcessName);
#endif
WindowInfo wi;
wi.setPID(pid);
wi.setWindowTitle(windowTitle);
wi.setProcessName(processName);
windowTitles.append(wi);
return windowTitles;
}
यहाँ लिनक्स/X11 के लिए कोड है::
linux_x11
यहाँ Windows API के लिए कोड है। एच
/*
Linux/X11 specific code for obtaining information about the frontmost window
*/
#ifndef LINUX_X11_H
#define LINUX_X11_H
#include <QtCore>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include "windowinfo.h"
class linux_x11
{
public:
linux_x11();
QList<WindowInfo> getActiveWindows();
private:
Window* active(Display *disp, unsigned long *len);
char *name (Display *disp, Window win);
int *pid(Display *disp, Window win);
QString processName(long pid);
};
#endif // LINUX_X11_H
linux_x11.cpp
/*
Linux/X11 specific code for obtaining information about the frontmost window
*/
#include "linux_x11.h"
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
linux_x11::linux_x11()
{
}
/**
* Returns the window name for a specific window on a display
***/
char *linux_x11::name (Display *disp, Window win) {
Atom prop = XInternAtom(disp,"WM_NAME",False), type;
int form;
unsigned long remain, len;
unsigned char *list;
if (XGetWindowProperty(disp,win,prop,0,1024,False,AnyPropertyType, &type,&form,&len,&remain,&list) != Success)
return NULL;
return (char*)list;
}
/**
* Returns the pid for a specific window on a display
***/
int* linux_x11::pid(Display *disp, Window win) {
Atom prop = XInternAtom(disp,"_NET_WM_PID",False), type;
int form;
unsigned long remain, len;
unsigned char *list;
if (XGetWindowProperty(disp,win,prop,0,1024,False,AnyPropertyType, &type,&form,&len,&remain,&list) != Success)
return NULL;
return (int*)list;
}
/**
* Returns the active window on a specific display
***/
Window * linux_x11::active (Display *disp, unsigned long *len) {
Atom prop = XInternAtom(disp,"_NET_ACTIVE_WINDOW",False), type;
int form;
unsigned long remain;
unsigned char *list;
if (XGetWindowProperty(disp,XDefaultRootWindow(disp),prop,0,1024,False,XA_WINDOW, &type,&form,len,&remain,&list) != Success)
return NULL;
return (Window*)list;
}
/**
* Returns process name from pid (processes output from /proc/<pid>/status)
***/
QString linux_x11::processName(long pid)
{
// construct command string
QString command = "cat /proc/" + QString("%1").arg(pid) + "/status";
// capture output in a FILE pointer returned from popen
FILE * output = popen(command.toStdString().c_str(), "r");
// initialize a buffer for storing the first line of the output
char buffer[1024];
// put the contents of the buffer into a QString
QString line = QString::fromUtf8(fgets(buffer, sizeof(buffer), output));
// close the process pipe
pclose(output);
// take right substring of line returned to get process name
return line.right(line.length() - 6).replace("\n", "");
}
QList<WindowInfo> linux_x11::getActiveWindows()
{
QList<WindowInfo> windowTitles;
unsigned long len;
Display *disp = XOpenDisplay(NULL);
Window *list;
char *n;
int* p;
list = (Window*)active(disp,&len);
if((int)len > 0)
{
for (int i=0;i<(int)len;i++) {
n = name(disp,list[i]);
p = pid(disp, list[i]);
long p_id = 0;
QString pName;
QString windowTitle;
if(p!=NULL)
{
p_id = *p; // dereference pointer for obtaining pid
pName = processName(p_id);
}
if(n!=NULL)
windowTitle = QString::fromUtf8(n);
WindowInfo wi;
wi.setWindowTitle(windowTitle);
wi.setProcessName(pName);
wi.setPID(p_id);
windowTitles.append(wi);
delete n;
delete p;
}
}
delete list;
XCloseDisplay (disp);
return windowTitles;
}
X11 कोड काफी बदसूरत और मुश्किल समझने के लिए प्राप्त कर सकते हैं, लेकिन यह आपके लिए प्रारंभ करने चाहिए। यह काफी समय से रहा है क्योंकि मैंने सीधे एक्स 11 के साथ निपटाया है, इसलिए मैं आपको बिल्कुल नहीं बता सकता कि प्रत्येक सहायक विधि क्या करती है।
मैं कोड को सारणी देता हूं कि कोड के प्रत्येक प्लेटफॉर्म विशिष्ट टुकड़े में एक ही विधि हस्ताक्षर होता है। फिर मैं जांचता हूं कि यह मैक ओएस एक्स, विंडोज, या लिनक्स पर संकलित किया गया था और सही कक्षाओं को तुरंत चालू करता है। यह इस प्रकार से सभी एक साथ बंधे है:
#include "windowtitlereader.h"
WindowTitleReader::WindowTitleReader()
{
qDebug() << "WindowTitleReader::WindowTitleReader()";
// refresh window reading every 10ms
timer = new QTimer(this);
timer->setInterval(10);
timer->start();
connect(timer, SIGNAL(timeout()), this, SLOT(getWindowTitle()));
}
WindowTitleReader::~WindowTitleReader()
{
delete timer;
delete m_pid;
delete m_processName;
}
void WindowTitleReader::getWindowTitle()
{
qDebug() << "WindowTitleReader::getWindowTitle()";
#ifdef Q_WS_WIN
win w;
m_activeWindows = w.getActiveWindows();
#endif
#ifdef Q_WS_MACX
Mac m;
m_activeWindows = m.getActiveWindows();
#endif
#ifdef Q_WS_X11
linux_x11 l;
m_activeWindows = l.getActiveWindows();
#endif
for(int i = 0; i < m_activeWindows.count(); i++)
qDebug() << "PID: " << m_activeWindows[i].getPID() << " Process Name: " << m_activeWindows[i].getProcessName() << " Window Title: " << m_activeWindows[i].getWindowTitle();
}
आप अगर आप चाहते हैं एक धीमी ताज़ा दर को ताज़ा दर को बदल सकते हैं, लेकिन मैं अद्यतन हर 10ms चल रहा हूँ खिड़की ध्यान केंद्रित पर एक के पास वास्तविक समय अद्यतन प्राप्त करने के लिए।
मैंने मुख्य रूप से वेब ब्राउज़र और वीडियो गेम के विंडो शीर्षक को पढ़ने के लिए इस पुस्तकालय को लिखा है, इसलिए मुझे अनुमान लगाया जा सकता है कि लोग अपने कंप्यूटर पर कितने समय तक खेल खेलते हैं। मैंने इसे एक गेम प्ले मीट्रिक ऐप के हिस्से के रूप में लिखा है जिसे मैं बना रहा हूं।
कृपया, लक्ष्य प्लेटफ़ॉर्म निर्दिष्ट करें। क्योंकि कोई क्रॉस-प्लेटफॉर्म तरीके नहीं हैं। –
क्या आपने विरासत QWidget से 'isVisible()' की कोशिश की है? – Joum
अधिकांश प्लेटफ़ॉर्म पर, "सक्रिय विंडो" अन्य सभी विंडो के ऊपर दिखाई दे रही है, लेकिन यह केवल एक पर्याप्त मानदंड है। यदि यह आपके लिए पर्याप्त है, तो 'QWidget :: isActiveWindow() 'जांचें। – arne