admin
2023-08-04 9dede2eaa1d3e68be387c5fd612eb48226a54c9d
HOST修改
15个文件已修改
1个文件已删除
347 ■■■■ 已修改文件
constant.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
gui_wx.py 88 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/index23-05-04.html 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/js/http.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/js/page.js 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kpl/gui.py 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kpl/gui.spec 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
kpl/kpl_api.py 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.py 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
network_util.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
opencv_util.py 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
res/codes.txt 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
res/setting.conf 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test.png 补丁 | 查看 | 原始文档 | blame | 历史
test.py 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
win32_util.py 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
constant.py
@@ -1,2 +1,3 @@
SERVER_HOST = "111.230.16.67"
SERVER_HOST = "43.138.167.68"
WEB_HOST = "192.168.3.252"
IS_TEST = False
gui_wx.py
@@ -318,15 +318,23 @@
import log
# 识别同花顺看盘页面上面的代码
def ocr_ths_code():
    hwnd = ths_util.get_ths_main_content_hwnd()
    if not hwnd:
        raise Exception("看盘页面句柄未获取到")
    # 句柄截图
    # 实际位置(左,上,右,下)
    rect = win32gui.GetWindowRect(hwnd)
    # hwnd_width = (rect[2] - rect[0]) * 15 // 10
    # 格式为:(上边距,宽度,高度)
    rect_ = setting.get_ths_auto_code_rect()
    img = win32_util.window_capture(hwnd, (0, rect_[0], rect_[1], rect_[0] + rect_[2]))
    scale = 1.5
    if len(rect_) > 3:
        scale = rect_[3]
    width = int((rect[2] - rect[0]) * scale)
    left = width - rect_[1]
    img = win32_util.window_capture(hwnd, (left, rect_[0], width - 1, rect_[0] + rect_[2]), scale)
    clip_img, details = opencv_util.clip_ths_code_area(img)
    start_time = time.time()
    code = ocr_util.recognize_code(clip_img)
@@ -342,73 +350,6 @@
    return code
#
# # 代码属性
# class CodeAttributeFrame(wx.Frame):
#     def __init__(self):
#         wx.Frame.__init__(self, None, -1, "属性",
#                           style=wx.CAPTION ^ wx.RESIZE_BORDER ^ wx.MINIMIZE_BOX ^ wx.CLOSE_BOX ^ wx.STAY_ON_TOP,
#                           size=(200, 300))
#         self.SetBackgroundColour(wx.Colour(224, 224, 224))
#         self.SetTransparent(230)
#         self.Bind(wx.EVT_CLOSE, self.OnExit)
#         # 读取配置信息
#         window_info = setting.get_code_attribute_window_info()
#         if window_info:
#             self.SetPosition(wx.Point(window_info[0], window_info[1]))
#             self.Size = wx.Size(window_info[2], window_info[3])
#
#         bs = wx.BoxSizer(wx.VERTICAL)
#
#         self.label_code_name = wx.StaticText(self, label="")
#
#         self.label_atrribute = wx.StaticText(self, label="")
#
#         self.label_error = wx.StaticText(self, label="")
#         self.label_error.SetForegroundColour(wx.Colour(255, 0, 0))
#
#         bs.Add(self.label_code_name, 0, wx.LEFT | wx.TOP, 10)
#         bs.Add(self.label_atrribute, 0, wx.LEFT | wx.TOP, 10)
#         bs.Add(self.label_error, 0, wx.LEFT | wx.TOP, 10)
#
#         self.SetSizer(bs)
#
#     def __request(self, code):
#         client = socket.socket()  # 生成socket,连接server
#         ip_port = (SERVER_HOST, SOCKET_PORT)  # server地址和端口号(最好是10000以后)
#         client.connect(ip_port)
#         data = {"type": 430, "data": {"code": code}}
#         client.send(json.dumps(data).encode("utf-8"))
#         result = client.recv(1024)
#         client.close()
#         return result.decode("gbk")
#
#     # 设置代码
#     def setCode(self, code):
#         # 获取代码属性描述
#         try:
#             result = self.__request(code)
#             result = json.loads(result)
#             if result['code'] == 0:
#                 code_info = result['data']['code_info']
#                 desc = result['data']['desc']
#                 self.label_code_name.SetLabelText(f"{code_info[1]}({code_info[0]})")
#                 self.label_atrribute.SetLabelText(desc)
#                 self.label_error.SetLabelText("")
#         except Exception as e:
#             self.label_code_name.SetLabelText("")
#             self.label_atrribute.SetLabelText("")
#             self.label_error.SetLabelText(str(e))
#
#     def OnExit(self, e):
#         try:
#             setting.set_code_attribute_window_info((self.Position[0], self.Position[1], self.Size[0], self.Size[1]))
#         except Exception as e:
#             print("")
#         self.Hide()
#
# 悬浮框
class FloatFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "悬浮盯盘", style=wx.CAPTION ^ wx.MINIMIZE_BOX ^ wx.CLOSE_BOX ^ wx.STAY_ON_TOP,
@@ -1038,7 +979,7 @@
    # 设置代码,请求代码属性
    def setCode(self, code):
        # 获取代码属性描述
        #auto_focus = setting.get_float_frame_auto_focus()
        # auto_focus = setting.get_float_frame_auto_focus()
        if True:
            print("是否有管理员权限", self.is_admin())
            # 窗口显示在最前面
@@ -1772,6 +1713,7 @@
if __name__ == "__main__":
    app = mainApp()
    app.MainLoop()
    # ths_auto_refresh()
    # app = mainApp()
    # app.MainLoop()
    # ocr_ths_code()
    print(int(1.5))
kp_html/kp/index23-05-04.html
@@ -319,12 +319,23 @@
                </div>
                <!-- 左侧 -->
                <div style="float: left;width: 27.5%;margin-right: 0.4%;" class="scroll-y">
                    <table style="width: 100%; background: #cecece;" class="shoubanzuogundong">
                        <thead></thead>
                        <thead>
                            <tr style="height: 40px;padding-right: 0;">
                                <td style="padding-right: 0;">
                                    <div style="display: flex;justify-content: space-between;">
                                    <input  type="text" placeholder="请输入名称搜索" style="width:70%" id="limit_up_search_key"/>
                                    <button class="layui-btn" v-on:click="limit_up_search">搜索</button>
                                    </div>
                                </td>
                            </tr>
                        </thead>
                        <tbody>
                            <tr v-for="(item,index) in first_info.limit_up_codes"
                                @click="select_code_level_1($event,index)"
                                :class="{'active':choose_code.first==item[0]}">
                                :class="{'active':choose_code.first==item[0]}" v-if="item[0].indexOf(limit_up_search_key)>=0">
                                <td>
                                    <div style="display:flex;justify-content:space-between;align-items:center">
@@ -602,9 +613,10 @@
            <!-- 弹出框 -->
            <div id="want_code_dialog" style="display: none;">
                <div v-if="want_codes" class="want_code_content" style="display: flex;width: 400px;justify-content: space-between;">
                    <div v-for="(item,i) in want_codes" class="item" style="display: flex;width: 180px;margin-bottom: 15px;">
                        <div>{{item[1]}}({{item[0]}}) <span class="red" v-if="item[2]==1">*</span> </div>
                <div v-if="want_codes" class="want_code_content" style="display: flex;width: 540px;justify-content: space-between;">
                    <div v-for="(item,i) in want_codes" class="item" style="display: flex;width: 220px;margin-bottom: 15px;">
                        <div><img :style="{'visibility':item[3]?'visiable':'hidden'}" style="margin-right:5px;" src="./images/stop_up.png" ><span :class="{'red': item[5]}">{{item[1]}}({{item[0]}})-{{item[2]}} </span><span class="red" v-if="item[4]">*</span> </div>
                        <img v-if="item[2]==1" class="delete" src="./images/delete.png"
                            @click="delete_from_want_codes(i)">
                    </div>
kp_html/kp/js/http.js
@@ -9,6 +9,7 @@
        return null;
    },
    http_request_result: function(key, data) {
        data = atob(data);
        console.log("http请求回调", "key:" + key);
        http_util.request_callback[key](data);
        delete http_util.request_callback[key];
@@ -16,6 +17,9 @@
    http_request: function(path, data, callback) {
        key = "http_callback_" + new Date().getTime() + "_" + Math.round(Math.random() * 100000000);
        http_util.request_callback[key] = callback;
        console.log("http请求路径", path,key);
        pyjs.http_request(path, JSON.stringify(data), JSON.stringify(["http_util.http_request_result", key]));
    },
kp_html/kp/js/page.js
@@ -84,6 +84,8 @@
            data: {
                code: "000000",
                code_name: "----",
                last_show_dialog:0,
                limit_up_search_key:'',
                trade_data: {
                    order: 0
                },
@@ -349,7 +351,10 @@
                    init_data();
                    _resize();
                },
                limit_up_search:function(){
                    key = $("#limit_up_search_key").val();
                    app.limit_up_search_key=key;
                },
                //获取行业数据
                get_industry_data: function(type) {
                    app.industry_data_type = type;
@@ -421,7 +426,6 @@
                get_limit_up_list: function(code, is_auto_refresh) {
                    http_util.get_limit_up_list(code, function(res) {
                        res = JSON.parse(res)
                        console.log(res)
                        if (res.code == 0) {
                            app.first_info = res.data
                            if (app.choose_code.first) {
@@ -563,6 +567,11 @@
                    init_data();
                },
                show_want_codes: function(plate) {
                    if (Date.now() - app.last_show_dialog<500){
                        return;
                    }
                    app.last_show_dialog= Date.now()
                    http_util.get_plate_codes(plate, function(result) {
                        result = JSON.parse(result);
                        console.log("涨停原因成分股返回:",result);
kpl/gui.py
@@ -169,6 +169,9 @@
        t1.setDaemon(True)
        t1.start()
        # 自动开启采集
        self.__start_all_task(None)
    def run_schedule(self):
        while True:
            schedule.run_pending()
@@ -212,54 +215,72 @@
    def __exec_limit_up(self):
        if not self.__can_capture(0):
            return
        results = kpl_api.daBanList(kpl_api.DABAN_TYPE_LIMIT_UP)
        result = json.loads(results)
        self.logger.info(f"涨停代码数量:{len(result['list'])}")
        self.__upload_data(self.keys[0], result)
        try:
            results = kpl_api.daBanList(kpl_api.DABAN_TYPE_LIMIT_UP)
            result = json.loads(results)
            self.logger.info(f"涨停代码数量:{len(result['list'])}")
            self.__upload_data(self.keys[0], result)
        except:
            pass
    def __exec_open_limit_up(self):
        if not self.__can_capture(1):
            return
        results = kpl_api.daBanList(kpl_api.DABAN_TYPE_OPEN_LIMIT_UP)
        result = json.loads(results)
        self.logger.info(f"炸板代码数量:{len(result['list'])}")
        self.__upload_data(self.keys[1], result)
        try:
            results = kpl_api.daBanList(kpl_api.DABAN_TYPE_OPEN_LIMIT_UP)
            result = json.loads(results)
            self.logger.info(f"炸板代码数量:{len(result['list'])}")
            self.__upload_data(self.keys[1], result)
        except:
            pass
    def __exec_limit_down(self):
        if not self.__can_capture(2):
            return
        results = kpl_api.daBanList(kpl_api.DABAN_TYPE_LIMIT_DOWN)
        result = json.loads(results)
        self.logger.info(f"跌停代码数量:{len(result['list'])}")
        self.__upload_data(self.keys[2], result)
        try:
            results = kpl_api.daBanList(kpl_api.DABAN_TYPE_LIMIT_DOWN)
            result = json.loads(results)
            self.logger.info(f"跌停代码数量:{len(result['list'])}")
            self.__upload_data(self.keys[2], result)
        except:
            pass
    def __exec_ever_limit_down(self):
        if not self.__can_capture(3):
            return
        results = kpl_api.daBanList(kpl_api.DABAN_TYPE_EVER_LIMIT_DOWN)
        result = json.loads(results)
        self.logger.info(f"曾经跌停代码数量:{len(result['list'])}")
        self.__upload_data(self.keys[3], result)
        try:
            results = kpl_api.daBanList(kpl_api.DABAN_TYPE_EVER_LIMIT_DOWN)
            result = json.loads(results)
            self.logger.info(f"曾经跌停代码数量:{len(result['list'])}")
            self.__upload_data(self.keys[3], result)
        except:
            pass
    def __exec_fengkou(self):
        if not self.__can_capture(4):
            return
        results = kpl_api.getFengKouList(tool.get_now_date_str())
        result = json.loads(results)
        self.logger.info(f"市场风口代码数量:{len(result['List'])}")
        self.__upload_data(self.keys[4], result)
        try:
            results = kpl_api.getFengKouList(tool.get_now_date_str())
            result = json.loads(results)
            self.logger.info(f"市场风口代码数量:{len(result['List'])}")
            self.__upload_data(self.keys[4], result)
        except:
            pass
    def __exec_fengkou_best(self):
        if not self.__can_capture(5):
            return
        if not os.path.exists("D:/kpl/GetFengKListBest_0_0.log"):
            return
        with open("D:/kpl/GetFengKListBest_0_0.log", mode='r', encoding="utf-16") as f:
            lines = f.readlines()
            if lines:
                data = json.loads(lines[0])
                self.logger.info(f"最强风口代码数量:{data['Count']}")
                self.__upload_data(self.keys[5], data)
        try:
            if not self.__can_capture(5):
                return
            if not os.path.exists("D:/kpl/GetFengKListBest_0_0.log"):
                return
            with open("D:/kpl/GetFengKListBest_0_0.log", mode='r', encoding="utf-16") as f:
                lines = f.readlines()
                if lines:
                    data = json.loads(lines[0])
                    self.logger.info(f"最强风口代码数量:{data['Count']}")
                    self.__upload_data(self.keys[5], data)
        except:
            pass
    def __exec_fengxiang(self):
        if not self.__can_capture(6):
@@ -276,18 +297,25 @@
    def __exec_industry_rank(self):
        if not self.__can_capture(7):
            return
        results = kpl_api.getMarketIndustryRealRankingInfo()
        result = json.loads(results)
        self.logger.info(f"行业涨幅排行代码数量:{len(result['list'])}")
        self.__upload_data(self.keys[7], result)
        try:
            results = kpl_api.getMarketIndustryRealRankingInfo()
            result = json.loads(results)
            self.logger.info(f"行业涨幅排行代码数量:{len(result['list'])}")
            self.__upload_data(self.keys[7], result)
        except:
            pass
    def __exec_jingxuan_rank(self):
        if not self.__can_capture(8):
            return
        results = kpl_api.getMarketJingXuanRealRankingInfo()
        result = json.loads(results)
        self.logger.info(f"精选流入排行代码数量:{len(result['list'])}")
        self.__upload_data(self.keys[8], result)
        try:
            results = kpl_api.getMarketJingXuanRealRankingInfo()
            result = json.loads(results)
            self.logger.info(f"精选流入排行代码数量:{len(result['list'])}")
            self.__upload_data(self.keys[8], result)
        except:
            pass
    # 开始所有的任务
    def __start_all_task(self, event):
@@ -309,7 +337,7 @@
            "type": type,
            "data": datas
        }
        requests.post("http://111.230.16.67:9004/upload_kpl_data", json.dumps(root_data))
        requests.post("http://43.138.167.68:9004/upload_kpl_data", json.dumps(root_data))
    def OnExit(self, e):
        sys.exit(0)
kpl/gui.spec
@@ -46,5 +46,5 @@
    strip=False,
    upx=True,
    upx_exclude=[],
    name='开盘啦2',
    name='开盘啦',
)
kpl/kpl_api.py
@@ -82,7 +82,7 @@
# 市场行情-行业
def getMarketIndustryRealRankingInfo(orderJingE_DESC=True):
    data = f"Order={ 1 if orderJingE_DESC else 0}&a=RealRankingInfo&st=20&apiv=w32&Type=5&c=ZhiShuRanking&PhoneOSNew=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&Index=0&ZSType=4&"
    data = f"Order={1 if orderJingE_DESC else 0}&a=RealRankingInfo&st=20&apiv=w32&Type=5&c=ZhiShuRanking&PhoneOSNew=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&Index=0&ZSType=4&"
    response = __base_request("https://apphq.longhuvip.com/w1/api/index.php",
                              data=data)
    if response.status_code != 200:
@@ -92,7 +92,7 @@
# 市场行情-精选
def getMarketJingXuanRealRankingInfo(orderJingE_DESC=True):
    data = f"Order={ 1 if orderJingE_DESC else 0}&a=RealRankingInfo&st=20&apiv=w32&Type=5&c=ZhiShuRanking&PhoneOSNew=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&Index=0&ZSType=7&"
    data = f"Order={1 if orderJingE_DESC else 0}&a=RealRankingInfo&st=20&apiv=w32&Type=5&c=ZhiShuRanking&PhoneOSNew=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&Index=0&ZSType=7&"
    response = __base_request("https://apphq.longhuvip.com/w1/api/index.php",
                              data=data)
    if response.status_code != 200:
@@ -129,6 +129,15 @@
    return response.text
# 获取涨幅排行
def get_jingxuan_block(code):
    data = f"a=GetStockIDPlate&apiv=w32&Type=2&c=StockL2Data&StockID={code}&PhoneOSNew=1&UserID=0&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&Token=0&"
    response = __base_request("https://apphq.longhuvip.com/w1/api/index.php", data=data)
    if response.status_code != 200:
        raise Exception("请求出错")
    return response.text
def test_l2():
    code = "600981"
    count = 0
@@ -143,15 +152,6 @@
if __name__ == '__main__':
    result = (getCodesByPlate("801085"))
    result = get_jingxuan_block("600753")
    result = json.loads(result)
    print(result["list"])
    result = (daBanList(DABAN_TYPE_LIMIT_UP))
    result = json.loads(result)
    print(len(result["list"]))
    tool.get_now_time_str()
    for d in result["list"]:
        print(d)
    # print("强度", getSonPlate("801270"))
    print(getMarketJingXuanRealRankingInfo(True))
    print(result["ListJX"])
main.py
@@ -1,3 +1,4 @@
import base64
import json
import logging
import multiprocessing
@@ -32,7 +33,8 @@
    signal_request = pyqtSignal(str, str, str)
    def __request_result_callback(self, method, key, result):
        self.__webview.page().runJavaScript(f"{method}('{key}','{result}')")
        base64_str = base64.b64encode(result.encode('utf-8')).decode('utf-8')
        self.__webview.page().runJavaScript(f"{method}('{key}','{base64_str}')")
    def __init__(self, webview):
        super().__init__()
@@ -42,7 +44,6 @@
    def __http_request(self, url, callback_info):
        try:
            result = network_util.http_get(url)
            print("请求结果:", result)
            self.signal_request.emit(callback_info[0], callback_info[1], result)
            return result
        except Exception as e:
@@ -384,12 +385,16 @@
        self.setCentralWidget(self.webview)
        self.show()
        self.webview.load(QUrl(f"http://{constant.WEB_HOST}/kp/index23-05-04.html"))
        # self.webview.load(QUrl("http://127.0.0.1:8848/kp/index23-05-04.html"))
        if not constant.IS_TEST:
            self.webview.load(QUrl(f"http://{constant.WEB_HOST}/kp/index23-05-04.html"))
        else:
            self.webview.load(QUrl("http://127.0.0.1:8848/kp/index23-05-04.html"))
        self.secondWindow.show()
        self.secondWindow.loadUrl(f"http://{constant.WEB_HOST}/kp/codes_list.html")
        # self.secondWindow.loadUrl("http://127.0.0.1:8848/kp/codes_list.html")
        if not constant.IS_TEST:
            self.secondWindow.loadUrl(f"http://{constant.WEB_HOST}/kp/codes_list.html")
        else:
            self.secondWindow.loadUrl("http://127.0.0.1:8848/kp/codes_list.html")
        # 绑定槽函数
        self.signal_update_code.connect(self.set_target_code)
network_util.py
@@ -21,7 +21,7 @@
def http_get(path):
    response = requests.get(f"http://{SERVER_HOST}:{HTTP_PORT}{path}")
    response = requests.get(f"http://{constant.SERVER_HOST}:{HTTP_PORT}{path}")
    if response.status_code == 200:
        return response.text
    return None
opencv_util.py
@@ -118,11 +118,11 @@
    if start_row < 0:
        raise Exception("没找到上分割线")
    end_col = cols - 1
    start_col = cols - 1
    for c in range(cols - 1, -1, -1):
        if is_col_full(img, c, start_row, end_row, 38, 38, 2):
            # print("找到分隔:", col)
            end_col = c - 1
            start_col = c + 1
            break
    # 往前找数字分隔
    content_start = -1
@@ -134,11 +134,11 @@
    # 获取代码的最大色值
    max_color = 0
    for r in range(start_row, end_row + 1):
        for c in range(end_col, end_col // 2, -1):
        for c in range(cols - 1, start_col + (cols - start_col) // 2, -1):
            if img[r][c] > max_color:
                max_color = img[r][c]
    for col in range(end_col, 0, -1):
    # 从后往前找
    for col in range(cols - 1, start_col, -1):
        if not is_col_empty(img, col, start_row, end_row, max_color * 2 // 3):
            if start_index < 0:
                start_index = col
res/codes.txt
@@ -1,2 +1,4 @@
000892
601519
002387
002813
001330
603286
res/setting.conf
@@ -1,12 +1,14 @@
[config]
stay_on_top = 1
window_info = [[-1711, 194, 1280, 800], [1473, 621, 320, 195]]
xgb_window_info = [-2161, 77, 1920, 1017]
window_watch_float_info = [-1075, 374, 435, 220]
window_tick_info = [-1919, 1, 1918, 1038]
kp_second_window_info = [-961, 751, 738, 890]
xgb_window_info = [-1921, -8, 1920, 1017]
window_watch_float_info = [-628, 346, 435, 220]
window_tick_info = [-1420, 79, 1027, 643]
kp_second_window_info = [-2320, 119, 1920, 1017]
code_attribute_window_info = [-650, 315, 291, 278]
client = hxh
float_frame_auto_focus = 1
float_frame_trade_quick_key = 1
[juejin]
strategy_id = 95a982ce-fc2d-11ec-8ff3-0a0027000010
test.png
Binary files differ
test.py
@@ -1,6 +1,7 @@
import datetime
import json
import sys
import threading
from PyQt5 import QtWidgets
from PyQt5.QtCore import QUrl
@@ -23,12 +24,13 @@
if __name__ == "__main__":
    # app = QtWidgets.QApplication(sys.argv)
    # browser = MainWindow()
    # sys.exit(app.exec())
    # test =""
    # print(test)
    n = datetime.datetime.now()
    data = {"t": n.microsecond}
    print(json.dumps(data))
    lock = threading.Lock()
    print(lock.locked())
    lock.acquire()
    lock.acquire()
    print(lock.locked())
    lock.release()
    print(lock.locked())
win32_util.py
@@ -44,13 +44,19 @@
    win32gui.PostMessage(hwnd, win32con.WM_KEYDOWN, code, 0)
    win32gui.PostMessage(hwnd, win32con.WM_KEYUP, code, 0)
def visual_keyboard_F5(hwnd):
    win32gui.PostMessage(hwnd, win32con.WM_KEYDOWN, win32con.VK_F5, 0)
    win32gui.PostMessage(hwnd, win32con.WM_KEYUP, win32con.VK_F5, 0)
def window_capture(hwnd, rect):
# rect格式为:(左,上,右,下坐标)
def window_capture(hwnd, rect, scale):
    rect_ = win32gui.GetWindowRect(hwnd)
    ow = rect_[2] - rect_[0]
    oh = rect_[3] - rect_[1]
    ow = int(ow * scale)
    oh = int(oh * scale)
    w = rect[2] - rect[0]
    h = rect[3] - rect[1]
    if w == 0 or h == 0:
@@ -68,9 +74,10 @@
    # 将截图保存到saveBitMap中
    saveDC.SelectObject(saveBitMap)
    # 保存bitmap到内存设备描述表
    saveDC.BitBlt((0, 0), (w, h), mfcDC, (rect[0], rect[1]), win32con.SRCCOPY)
    saveDC.BitBlt((0, 0), (ow, h), mfcDC, (rect[0], rect[1]), win32con.SRCCOPY)
    # saveDC.BitBlt((0, 0), (w, h), mfcDC, (0, 0), win32con.SRCCOPY)
    # 保存数据
    saveBitMap.SaveBitmapFile(saveDC, "test.png")
    # saveBitMap.SaveBitmapFile(saveDC, "test.png")
    signedIntsArray = saveBitMap.GetBitmapBits(True)
@@ -89,7 +96,6 @@
if __name__ == "__main__":
    # print(search_window("副屏1"))
    # visual_click(0x00152876, (110, 90))
    x = 1500 +67
    y = 400 + 4
    window_capture(0x00010BA2,(x,y,x +45,y+16))
    window_capture(0x00010986, (0, 0, 1920, 895))
    # pass