Найдите окно и измените его имя

Как дела

То, что я пытаюсь сделать, - это способ найти окно, хотя его идентификатор процесса, получить имя этого окна и изменить его на то, что я хочу.

Я нашел кое-что об этом: (Код 1)

 int WINAPI GetWindowText(
   _In_  HWND   hWnd,
   _Out_ LPTSTR lpString,
   _In_  int    nMaxCount
    );

это: (Код 2)

    CWnd* pWnd = GetDlgItem(); GetDlgIt
pWnd->SetWindowText(_T("WindowName"));


CString str;
pWnd->GetWindowText(str);
ASSERT(str == _T("WindowName"));

а также это (Код 3)

    HWND WindowHandel = FindWindowA(0, "WindowName"); 

    DWORD proccesID = 0

    GetWindowThreadProcessId(WindowHandel, &proccesID);

Мои вопросы: как я могу получить идентификатор процесса, получить имя окна этого процесса, поместить его, чтобы коды могли распознавать Hwnd как имя моего окна и изменить его на то, что я хочу. Что-то вроде этого :

Process = "anyprocess.exe"
Get Process ID <
Process ID = 1234567
Get window name from the ProcessID we have <
Window name = "ILoveYou"
Change "ILoveYou" to "IHaveYou"

И если у меня есть более одного окна с тем же именем, есть ли способ проверить первое открытое, чтобы я не менял другие окна?

На мой взгляд, брать WindowName из идентификатора процесса кажется более безопасным, дело в том, что я не хочу говорить коду, что знаю имя окна, я хочу, чтобы он нашел его и изменил его, как это сделал Лиам Нисон с этими плохие парни.

И я также хотел бы узнать больше об использовании этих "(0,...." или "(NULL,....", команда "FindWindowA" была просто примером, я всегда это вижу и не знаю как им правильно пользоваться:

    FindWindowA(0, "WindowName")

Пример того, что я хочу, очень поможет мне =) Спасибо за ваше терпение.


person Bruno Cerk    schedule 10.03.2016    source источник


Ответы (2)


Нет, этого делать нельзя. Один и тот же PID может быть у нескольких окон.

Однако, предполагая, что целевое приложение является однопоточным и имеет только одно видимое окно, вы можете просмотреть все окна и проверить их PID, чтобы найти совпадение. Вы должны пропустить невидимые окна. Или, что еще лучше, пропустите окна без Alt-Tab. Вот как это делается.

Обратите внимание, я просто написал это для развлечения, я бы сам не поместил это ни в какое приложение.

BOOL IsAltTabWindow(HWND hwnd)
{
    if (!IsWindowVisible(hwnd)) return FALSE;

    HWND next = NULL;
    HWND parent = GetAncestor(hwnd, GA_ROOTOWNER);
    while (parent != next)
    {
        next = parent;
        parent = GetLastActivePopup(parent);
        if (IsWindowVisible(parent)) break;
    }
    if (next != hwnd) return FALSE;

    TITLEBARINFO ti = { 0 };
    ti.cbSize = sizeof(ti);
    GetTitleBarInfo(hwnd, &ti);
    if (ti.rgstate[0] & STATE_SYSTEM_INVISIBLE) return FALSE;

    if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) return FALSE;

    return TRUE;
}

BOOL CALLBACK enumProc(HWND hwnd, LPARAM lp)
{
    DWORD search_pid = DWORD(lp);
    if (!IsAltTabWindow(hwnd))
        return 1;
    DWORD pid = 0;
    GetWindowThreadProcessId(hwnd, &pid);
    if (pid != search_pid) return 1;
    SetWindowText(hwnd, "un-advised code");
    return 0;
}

int main()
{
    DWORD search_pid = 0;
    HWND hwnd = FindWindow(0, "Find me");
    GetWindowThreadProcessId(hwnd, &search_pid);

    EnumWindows(enumProc, LPARAM(search_pid));

    return 0;
}


Правка, объяснение:

Попробуйте код ниже. Сначала запустите блокнот Windows, убедитесь, что есть только один экземпляр блокнота.

Если вы запустите приведенный ниже код в Windows 10, он покажет не одно, а 3 окна с тем же PID, что и Блокнот. 2 из этих окон невидимы, они используются операционной системой, мы не должны их трогать.

Итак, мы хотим, по крайней мере, пропустить невидимые окна. Есть ряд других системных окон, мы тоже не хотим иметь с ними ничего общего.

IsAltTabWindow - хороший способ избежать этих окон. Это гарантирует, что мы просматриваем только те окна, к которым можно получить доступ с помощью клавиши Alt-Tab.

int main()
{
    HWND hwnd = FindWindow("Notepad", 0);
    if (!hwnd) return 0;
    DWORD search_pid = 0;
    GetWindowThreadProcessId(hwnd, &search_pid);

    for (hwnd = GetWindow(GetDesktopWindow(), GW_CHILD); 
        hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT))
    {
        char buf[300];
        GetWindowText(hwnd, buf, 300);

        DWORD pid = 0;
        GetWindowThreadProcessId(hwnd, &pid);
        if (pid == search_pid)
            std::cout << pid << "\n";
    }

    return 0;
}
person Barmak Shemirani    schedule 11.03.2016
comment
Почему бы вам не использовать его в приложении? А что это за if (next != hwnd) return FALSE; TITLEBARINFO ti = { 0 }; ti.cbSize = sizeof(ti); GetTitleBarInfo(hwnd, &ti); if (ti.rgstate[0] & STATE_SYSTEM_INVISIBLE) return FALSE; if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) return FALSE; return TRUE; - person Bruno Cerk; 11.03.2016
comment
Предположим, что целевой exe. я ищу только одно окно, и я хочу, чтобы когда я выполняю свою программу, она меняла имя один раз, просто когда я ее запускаю, она перестает пытаться найти идентификатор и окно и изменить его, разве это не возможно ? - person Bruno Cerk; 11.03.2016
comment
Смотрите редактирование для получения дополнительных объяснений. Причина, по которой я бы не стал использовать, заключается главным образом в том, что для этого нет практической причины. Если внешние окна мои, то я должен найти способ их найти. Например, используя имя класса или какой-то обмен сообщениями между окнами, это будет более надежным и эффективным. - person Barmak Shemirani; 11.03.2016

Вы могли бы взглянуть на это старое приложение на основе MFC, опубликованное на www.codeguru.com 15 лет назад (время летит...).

Вас может заинтересовать механизм получения HWND на основе щелчка мышью по экрану.

http://www.codeguru.com/cpp/misc/samples/article.php/c1465/Password-Retrieval-Application.htm

Z.

person Zyend    schedule 10.03.2016