如何找到当前的输入语言

时间:2019-01-17 19:00:45

标签: c++ winapi

我正在尝试制作一个获取进程名称,找到其ID的程序, 然后使用函数GetKeyboardLayout查找语言。

尽管我遇到困难,但似乎无法正常工作。 尽管返回的语言始终为00000000,但它会找到processID。

那是我的代码:

#include <iostream>
#include <windows.h>
#include <string>
#include <tlhelp32.h>

DWORD FindProcessId(LPCTSTR ProcessName);

int main() {
    HKL currentKBLayout;
    DWORD processID;

    LPCTSTR processName = "chrome.exe";
    while (true) {
            processID = FindProcessId(processName);
            if (processID == 0); // TODO: pause system for 5 seconds
            else { 
                currentKBLayout = GetKeyboardLayout(processID);
                std::cout << processID << " | "<< currentKBLayout << std::endl;
            }
    }
    system("pause");
    return 0;
}
DWORD FindProcessId(LPCTSTR ProcessName)
{
    PROCESSENTRY32 pt;
    HANDLE hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    pt.dwSize = sizeof(PROCESSENTRY32);
    if (Process32First(hsnap, &pt)) { // must call this first
        do {
            if (!lstrcmpi(pt.szExeFile, ProcessName)) {
                CloseHandle(hsnap);
                return pt.th32ProcessID;
            }
        } while (Process32Next(hsnap, &pt));
    }
    CloseHandle(hsnap); // close handle on failure
    return 0;
}


1 个答案:

答案 0 :(得分:1)

我同意雷米斯(Remys)的评论,即如果需要的话,可以使用一种更简单的方法来获取进程的键盘布局。但是,如果您有兴趣使用快照将更多信息添加到当前方法中,则可以采用这种方法。它拍摄所有进程和线程的快照。每个Process具有vector个对象中的Thread个。通过ThreadProcess对象添加到每个unordered_map<processId, Process>中。为了获得每个进程的唯一键盘布局集(因为每个线程理论上都可以拥有自己的键盘布局),请使用unordered_set<HKL>

#include "pch.h"
#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>

#include <windows.h>
#include <tlhelp32.h>

struct Thread {
    DWORD m_id;
    HKL m_keyboard_layout;

    Thread(DWORD Id) :
        m_id(Id), m_keyboard_layout(GetKeyboardLayout(m_id))
    {}
};

struct Process {
    std::vector<Thread> m_threads;
    DWORD m_id;
    std::wstring m_exefile;

    Process() = default;
    Process(DWORD Id, std::wstring Name) :
        m_id(Id), m_exefile(Name) 
    {}

    // get a unique set of HKL:s from all the threads in the process 
    std::unordered_set<HKL> GetKeyboardLayouts() const {
        std::unordered_set<HKL> rv;
        for (auto& t : m_threads) {
            if(t.m_keyboard_layout) // does it have a keyboard layout?
                rv.emplace(t.m_keyboard_layout);
        }
        return rv;
    }

    // if you'd like to iterate over the individual threads
    std::vector<Thread>::iterator begin() { return m_threads.begin(); }
    std::vector<Thread>::iterator end() { return m_threads.end(); }
};

class Snapshot {
    HANDLE hSnap;
    std::unordered_map<DWORD, Process> m_processes;

    void GetProcesses() {
        PROCESSENTRY32 pt;
        pt.dwSize = sizeof(pt);
        if (Process32First(hSnap, &pt)) { // must call this first
            do {
                m_processes[pt.th32ProcessID] = Process(pt.th32ProcessID, pt.szExeFile);
            } while (Process32Next(hSnap, &pt));
        }
    }

    void GetThreads() {
        THREADENTRY32 pt;
        pt.dwSize = sizeof(pt);
        if (Thread32First(hSnap, &pt)) { // must call this first
            do {
                m_processes[pt.th32OwnerProcessID].m_threads.emplace_back(pt.th32ThreadID);
            } while (Thread32Next(hSnap, &pt));
        }
    }

    void Populate() {
        GetProcesses();
        GetThreads();
    }
public:
    Snapshot() :
        hSnap(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0)),
        m_processes()
    {
        // TODO: make this exception better
        if (hSnap == INVALID_HANDLE_VALUE) throw GetLastError();
        Populate();
        CloseHandle(hSnap);
    }

    std::unordered_map<DWORD, Process>::iterator begin() { return m_processes.begin(); }
    std::unordered_map<DWORD, Process>::iterator end() { return m_processes.end(); }
};

int main() {
    Snapshot snap;

    // show processes with keyboard layouts
    for (const auto& m : snap) { // std::pair  m.first = processId, m.second = Process

        const Process& p = m.second;    
        auto layouts = p.GetKeyboardLayouts();

        if (layouts.size()) { // only show processes with keyboard layouts
            std::wcout << p.m_id << L" " << p.m_exefile << L"\n";

            for (const auto& l : layouts) {
                std::wcout << L" layout " << l << L"\n";
            }
        }
    }

    return 0;
}