[Share Experiences] linux微信显示和隐藏微信窗口
Tofloor
poster avatar
liwl
deepin
7 hours ago
Author

linux版本微信截止到最新版本4.1.0,官方也还未给出打开和隐藏窗口的快捷键。因此用deepin自带的系统快捷键,配置了一个官替版本。

首先安装依赖,命令行执行:

sudo apt install wmctrl qdbus


创建源码程序,当然离不开AI辅助

#include 
#include 
#include 
#include 
#include 
#include 
#include 

class WeChatController {
private:
    std::vector executeCommand(const std::string& cmd) {
        std::vector result;
        FILE* pipe = popen(cmd.c_str(), "r");
        if (!pipe) return result;
  
        char buffer[128];
        while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
            std::string line(buffer);
            if (!line.empty() && line.back() == '\n') {
                line.pop_back();
            }
            result.push_back(line);
        }
        pclose(pipe);
        return result;
    }

    std::string getWeChatPid() {
        auto pids = executeCommand("pgrep -x wechat");
        return pids.empty() ? "" : pids[0];
    }

    std::vector getWeChatWindows() {
        return executeCommand("xdotool search --class 'wechat'");
    }

    std::string getActiveWindow() {
        auto windows = executeCommand("xdotool getactivewindow");
        return windows.empty() ? "" : windows[0];
    }

    void activateWeChatTrayIcon() {
        std::string wechat_pid = getWeChatPid();
        if (wechat_pid.empty()) {
            exit(1);
        }

        auto items = executeCommand("qdbus org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.kde.StatusNotifierWatcher.RegisteredStatusNotifierItems");
  
        for (const auto& item : items) {
            if (item.find(wechat_pid) != std::string::npos) {
                size_t pos = item.find('/');
                if (pos != std::string::npos) {
                    std::string item_name = item.substr(0, pos);
                    std::string cmd = "dbus-send --session --type=method_call --dest=\"" + 
                                     item_name + "\" /StatusNotifierItem org.kde.StatusNotifierItem.Activate int32:0 int32:0";
                    system(cmd.c_str());
                    break;
                }
            }
        }
    }

public:
    void run() {
        // 获取微信窗口和当前活动窗口
        auto wechat_windows = getWeChatWindows();
        std::string current_window = getActiveWindow();
  
        bool found = false;
        std::string active_wechat_window;

        // 检查当前活动窗口是否是微信窗口
        for (const auto& window_id : wechat_windows) {
            if (current_window == window_id) {
                found = true;
                active_wechat_window = window_id;
                break;
            }
        }

        // 切换逻辑
        if (found) {
            // 微信窗口是当前活动窗口,关闭它
            if (system("which wmctrl > /dev/null 2>&1") == 0) {
                std::string cmd = "wmctrl -ic " + active_wechat_window;
                system(cmd.c_str());
            } else {
                // 备用方案:发送 Alt+F4
                std::string cmd = "xdotool key --window " + active_wechat_window + " alt+F4";
                system(cmd.c_str());
            }
        } else {
            // 微信窗口不是当前活动窗口,激活第一个微信窗口
            if (!wechat_windows.empty()) {
                std::string cmd = "xdotool windowactivate " + wechat_windows[0];
                system(cmd.c_str());
                activateWeChatTrayIcon();
            } else {
                std::cout << "未找到微信窗口" << std::endl;
            }
        }
    }
};

int main() {
    WeChatController controller;
    controller.run();
    return 0;
}

代码保存为:wechat.cpp
命令行编译:g++ -std=c++11 -o wechat wechat.cpp

把wechat放到喜欢的地方,比如:/home/liwl/.liwl/tools/
配置全局快捷键路径:

597042-20251112180406605-1110872711.png

这样就可以了,调整为自己喜欢的快捷键即可。我用的deepin v20.9,没毛病。

Reply Favorite View the author
All Replies
泡沫
deepin
6 hours ago
#1

感谢大神 大神辛苦

Reply View the author
qq4945286
deepin
5 hours ago
#2

如果是双微信的,就把代码换成

#include 
#include 
#include 
#include 
#include 
#include 
#include 

class WeChatController {
private:
    // 执行系统命令并返回结果列表
    std::vector executeCommand(const std::string& cmd) {
        std::vector result;
        FILE* pipe = popen(cmd.c_str(), "r");
        if (!pipe) return result;

        char buffer[128];
        while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
            std::string line(buffer);
            if (!line.empty() && line.back() == '\n') {
                line.pop_back();
            }
            result.push_back(line);
        }
        pclose(pipe);
        return result;
    }

    // 获取窗口标题(用于筛选主窗口)
    std::string getWindowTitle(const std::string& windowId) {
        std::string cmd = "xdotool getwindowname " + windowId;
        auto titles = executeCommand(cmd);
        return titles.empty() ? "" : titles[0];
    }

    // 筛选微信账号主窗口(标题包含“微信”,排除子窗口)
    std::vector getWeChatMainWindows() {
        std::vector allWeChatWindows = executeCommand("xdotool search --class 'wechat'");
        std::vector mainWindows;

        for (const auto& winId : allWeChatWindows) {
            std::string title = getWindowTitle(winId);
            // 筛选标题包含“微信”的窗口(主窗口特征),可根据实际标题调整关键词
            if (title.find("微信") != std::string::npos) {
                mainWindows.push_back(winId);
            }
        }

        // 若未筛选到(可能标题为英文“ WeChat ”),降级保留所有窗口(避免失效)
        if (mainWindows.empty()) {
            mainWindows = allWeChatWindows;
        }

        return mainWindows;
    }

    // 获取当前活动窗口ID
    std::string getActiveWindow() {
        auto windows = executeCommand("xdotool getactivewindow");
        return windows.empty() ? "" : windows[0];
    }

    // 激活对应微信的托盘图标(按窗口PID精准匹配,避免多账号混淆)
    void activateWeChatTrayIcon(const std::string& windowId) {
        std::string pidCmd = "xdotool getwindowpid " + windowId;
        auto pids = executeCommand(pidCmd);
        if (pids.empty()) return;
        std::string wechatPid = pids[0];

        auto trayItems = executeCommand("qdbus org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.kde.StatusNotifierWatcher.RegisteredStatusNotifierItems");
        for (const auto& item : trayItems) {
            if (item.find(wechatPid) != std::string::npos) {
                size_t pos = item.find('/');
                if (pos != std::string::npos) {
                    std::string itemName = item.substr(0, pos);
                    std::string activateCmd = "dbus-send --session --type=method_call --dest=\"" + 
                                             itemName + "\" /StatusNotifierItem org.kde.StatusNotifierItem.Activate int32:0 int32:0";
                    system(activateCmd.c_str());
                    break;
                }
            }
        }
    }

public:
    void run() {
        // 只获取微信主窗口(排除子窗口)
        std::vector wechatMainWindows = getWeChatMainWindows();
        std::string currentActiveWindow = getActiveWindow();

        if (wechatMainWindows.empty()) {
            std::cout << "未找到微信主窗口(请确保微信已启动)" << std::endl;
            return;
        }

        // 打印主窗口ID(方便调试,可删除)
        std::cout << "检测到微信主窗口数量:" << wechatMainWindows.size() << std::endl;
        for (const auto& winId : wechatMainWindows) {
            std::cout << "主窗口ID:" << winId << " | 标题:" << getWindowTitle(winId) << std::endl;
        }

        // 检查当前活动窗口是否是微信主窗口
        bool isWeChatActive = false;
        std::string targetWindowId = "";
        for (const auto& winId : wechatMainWindows) {
            if (winId == currentActiveWindow) {
                isWeChatActive = true;
                targetWindowId = winId;
                break;
            }
        }

        if (isWeChatActive) {
            // 场景1:当前聚焦微信主窗口 → 仅隐藏该窗口(不影响其他账号/子窗口)
            if (system("which wmctrl > /dev/null 2>&1") == 0) {
                std::string hideCmd = "wmctrl -ic " + targetWindowId;
                system(hideCmd.c_str());
                std::cout << "已隐藏微信窗口:" << targetWindowId << std::endl;
            } else {
                std::string altF4Cmd = "xdotool key --window " + targetWindowId + " alt+F4";
                system(altF4Cmd.c_str());
                std::cout << "已通过Alt+F4关闭微信窗口:" << targetWindowId << std::endl;
            }
        } else {
            // 场景2:当前未聚焦微信 → 激活最近使用的微信主窗口(可自定义优先级)
            // 若想固定激活第一个账号:targetWindowId = wechatMainWindows[0]
            // 若想固定激活第二个账号:targetWindowId = wechatMainWindows[1](需确保至少2个主窗口)
            targetWindowId = wechatMainWindows[0]; // 默认激活最近使用的主窗口

            // 激活目标主窗口
            std::string activateCmd = "xdotool windowactivate " + targetWindowId;
            system(activateCmd.c_str());
            activateWeChatTrayIcon(targetWindowId); // 激活对应托盘图标,避免显示异常
            std::cout << "已激活微信窗口:" << targetWindowId << " | 标题:" << getWindowTitle(targetWindowId) << std::endl;
        }
    }
};

int main() {
    WeChatController controller;
    controller.run();
    return 0;
}

01.gif

Reply View the author