在另一个线程(不是主线程)中创建窗口

2023-11-23

我有一个功能:

HWND createMainWindow(P2p_Socket_Machine * toSend){

    HWND hMainWnd = CreateWindow( 
        L"Class",/*(LPCWSTR) nameOfConference.c_str()*/L"Chat",  WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, 
    CW_USEDEFAULT, 0, 600,400, 
    (HWND)NULL, (HMENU)NULL, 
    /*(HINSTANCE)hlnstance*/NULL, NULL 
    ); 

    if (!hMainWnd) { 
        MessageBox(NULL, L"Cannot create main window", L"Error", MB_OK); 
        return 0; 
    }

    CreateWindowA("LISTBOX",NULL, WS_CHILD|WS_VISIBLE|WS_BORDER|WS_VSCROLL|LBS_NOTIFY|LBS_MULTIPLESEL,310,30,255,275,hMainWnd,(HMENU)List_Box,NULL,NULL);

    CreateWindowExA(NULL,"BUTTON", "Refresh", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,385,310,100,24,hMainWnd,(HMENU)Button_Refresh, NULL ,NULL);

    CreateWindowExA(NULL,"BUTTON", "Send", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,385,334,100,24,hMainWnd,(HMENU)Button_Send, NULL ,NULL);

    CreateWindowExA(NULL,"BUTTON", "New", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,385,354,100,24,hMainWnd,(HMENU)Button_New, NULL ,NULL);

    CreateWindowA("EDIT",0,WS_BORDER|WS_VISIBLE|WS_CHILD|ES_LEFT|ES_MULTILINE|WS_VSCROLL|WS_DISABLED,
    10,30,265,275,hMainWnd,(HMENU)Text_Box_Get,NULL,NULL);

    CreateWindowA("EDIT",0,WS_BORDER|WS_VISIBLE|WS_CHILD|ES_LEFT|ES_MULTILINE|WS_VSCROLL,
    10,320,265,45,hMainWnd,(HMENU)Text_Box_Send,NULL,NULL);

    SetWindowLongPtr(hMainWnd,GWLP_USERDATA,(LONG_PTR)toSend);

    ShowWindow(hMainWnd, SW_SHOW); 
    //UpdateWindow(hMainWnd);

    return hMainWnd;

}

这是我的程序的主要部分:

int WINAPI WinMain(HINSTANCE hlnstance, HINSTANCE hPrevInstance, LPSTR IpCmdLine, int 
nCmdShow) 
{
WNDCLASSEX wc; 
    wc.cbSize = sizeof(wc); 
    wc.style = CS_HREDRAW | CS_VREDRAW; 
    wc.lpfnWndProc = MyFunc; 
    wc.cbClsExtra = 0; 
    wc.cbWndExtra = 0; 
    wc.hInstance = hlnstance; 
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL; 
    wc.lpszClassName = L"Class"; 
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
HWND toSend = createMainWindow(P2pSocket);

//some code

hThread = CreateThread(NULL, 0, ClientThread, 
            Message2, 0, &dwThreadId);

        if (hThread == NULL)
        {
            cout<<"Create thread filed";
            exit(10);
        }


    while (GetMessage(&msg, NULL, 0, 0)) { 

        TranslateMessage(&msg); 
        DispatchMessage(&msg);

    }

    return msg.wParam;   

当我在程序的主要部分调用函数 createMainWindow() 时 它按预期工作,但是当我运行它时 我的线程(ClientThread)不起作用。我读过我应该只在主线程中创建窗口。这是真的吗?如果这是真的,那么从另一个线程调用这个函数并在主线程中完成的最简单的方法是什么?


感谢大家。现在我知道了问题所在,但我坚持解决方案。 我的客户端线程代码是:

while(1){

    vector<HWND> AllHandlers;

    pair<string,string> Answer = Pointer->receiveMsgByUdp();

    if(!Pointer->isMyLocalAddress(Answer.first)){

        int type = messageUdpContentType(Answer.second);

        switch(type){

        case 0 :

            Pointer->sendMsgToIpUdp(Answer.first,"<?xml version='1.0'?><accepted/>");
            AllHandlers = getAllHandlersOfElementsOnWindowsByIdentityCode(Pointer->getAllHandlers(),List_Box);
            for(vector<HWND>::iterator j = AllHandlers.begin();j!=AllHandlers.end();j++)
                if(SendMessageA(*j, LB_FINDSTRINGEXACT, 0, (LPARAM)Answer.first.c_str())==LB_ERR)
                    SendMessageA(*j, LB_ADDSTRING, 0, (LPARAM)Answer.first.c_str());

            break;

        case 1 :
            AllHandlers = getAllHandlersOfElementsOnWindowsByIdentityCode(Pointer->getAllHandlers(),List_Box);
            for(vector<HWND>::iterator j = AllHandlers.begin();j!=AllHandlers.end();j++)
                if(SendMessageA(*j, LB_FINDSTRINGEXACT, 0, (LPARAM)Answer.first.c_str())==LB_ERR)
                    SendMessageA(*j, LB_ADDSTRING, 0, (LPARAM)Answer.first.c_str());

            break;

        case 2 :
            AllHandlers = getAllHandlersOfElementsOnWindowsByIdentityCode(Pointer->getAllHandlers(),List_Box);
            for(vector<HWND>::iterator j = AllHandlers.begin();j!=AllHandlers.end();j++)
                if((i = SendMessageA(*j, LB_FINDSTRINGEXACT, 0, (LPARAM)Answer.first.c_str()))!=LB_ERR)
                    SendMessageA(*j,LB_DELETESTRING, 0, (LPARAM)Answer.first.c_str());

            break;

        case 3 :

            userReply = MessageBoxW(NULL, L"Принять приглашение на конференцию?",
                    L"", MB_YESNO | MB_ICONQUESTION); 
            if (userReply==IDYES){

                //todo: Проверка на создание встречи, в которой уже состоишь
                string nameOfConf = fetchNameOfInviteConf(Answer.second);
                Pointer->createConference(nameOfConf);
                HWND toSendTo = createMainWindow(Pointer);
                Pointer->setHandlerInfo(nameOfConf,toSendTo);               
                Pointer->addNewMemberToConference_ServerType(nameOfConf,Answer.first);
                string toSend = string("<?xml version='1.0'?><inviteAccepted>") + nameOfConf + string("</inviteAccepted>");
                Pointer->sendMsgToIpUdp(Answer.first,toSend);

            }
            break;

        case 4 :

            string nameOfConf = fetchNameOfInviteAcceptConf(Answer.second);

            toSend.clear();
            Participants.clear();
            Participants = Pointer->getCurrentParticipants(nameOfConf);
            toSend+="<?xml version='1.0'?>";
            toSend+="<conference>";
            toSend+="<nameOfConference>";
            toSend+=nameOfConf;
            toSend+="</nameOfConference>";
            for(vector<string>::iterator i = Participants.begin();i!=Participants.end();i++){
                toSend+="<participant>" + *i + "</participant>";
            }
            toSend+="</conference>";



            Pointer->addNewMemberToConference_ClientType(nameOfConf,Answer.first);

            Pointer->sendToIpTcp(Answer.first,toSend);

            break;

    }

函数 receiveMsgByUdp() 停止该线程直到收到消息。对于缺乏知识,我深表歉意,但是我可以使用哪些功能或其他东西来解决这个问题。我应该重写我的方法 receiveMsgByUdp() 为异步方法还是如何调用函数 createMainWindow() 在主线程上运行?关于最后一个变体:我如何在纯 winapi 中执行此操作,我找不到任何简单的示例。有人可以给出代码片段吗。再次感谢)


您确实可以在主 UI 线程以外的线程中创建窗口。但是,这些窗口将与创建它们的线程具有亲和力,并且您将需要在创建窗口的每个线程中运行消息泵。

因此,虽然您可以按照您的要求进行操作,但 Win32 确实设计用于与同一线程具有亲和力的进程中的所有窗口一起工作。创建多个 UI 线程确实没有任何好处。你所要做的就是让你的生活变得异常且不必要的复杂。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在另一个线程(不是主线程)中创建窗口 的相关文章

  • 从 Dropbox C# 下载文件[重复]

    这个问题在这里已经有答案了 我正在尝试下载 Dropbox 中的 pdf 文件 我需要将其保存到本地计算机中 可以是任何文件夹C Users User Desktop例如 这是我一直在使用的代码 public void DownloadPd
  • 数据结构的优化存储以实现快速查找和持久化

    Scenario 我有以下方法 public void AddItemSecurity int itemId int userIds public int GetValidItemIds int userId 最初我正在考虑表单上的存储 i
  • ASP.NET 会员电子邮件验证

    尝试基于 C 创建电子邮件验证本文 https web archive org web 20211020153319 https www 4guysfromrolla com articles 062508 1 aspx 我创建了一个 ja
  • 如何将异常对象序列化为 xml 字符串

    我想要类似的东西 try code here catch Exception ex stringXML Exception toXML 这样 stringXML 的值就是
  • Windows 10 UWP 中的视觉状态管理器未在页面加载时应用初始状态

    我有一个带有相关面板的页面 可以根据宽度重新组织 但是 除非宽度 gt 720px 否则它似乎不会在加载时应用任何状态 如果我在加载页面后调整页面大小 则两种状态都有效 解决方法是检查加载页面上的窗口大小并手动选择状态 但我相信这应该自动处
  • 函数的不明确的引用/值版本

    考虑以下函数原型 void Remove SomeContainer Vec const std size t Index SomeContainer Remove SomeContainer Vec const std size t In
  • ASP.NET 数据集 getdataBy 无法启用约束。一行或多行包含违反非空、唯一或外键约束的值

    你好 我有一个非常简单的网络表单 我在此表单上有一个按钮和一个网格视图 以及一个包含链接表 bill docket docket bill 等的数据集 在按钮上单击我使用以下代码 protected void button click ob
  • 使用 CMake 对 SDL 的未定义引用

    我正在使用 SDL v1 2 15 7 和 CMake 3 2 1 开发一个项目 在 h 文件中我添加了 include
  • 对无符号 8 位整数进行左移操作 [重复]

    这个问题在这里已经有答案了 我试图理解 C C 中的移位运算符 但它们给我带来了困难 我有一个无符号 8 位整数 初始化为一个值 例如 1 uint8 t x 1 根据我的理解 它在内存中的表示方式如下 0 0 0 0 0 0 0 1 现在
  • Math.Sin、Math.Cos 和 Math.Tan 精度以及正确显示它们的方法

    我正在用 C 编写一个计算器 textBoxResult是一个文本框 我在其中显示数字 recount是以度为单位获取角度并以弧度为单位返回的函数 我的角度是从texBoxInput public double recount int nu
  • 二维数组的列求和

    我有一个IEnumerable
  • 本地主机和 request.Url.Authority

    我的应用程序通过 URL 中的公司标识符分隔用户 company1 app com company2 app com 我正在本地 PC 上进行测试 请求如下 company1 localhost com 但是 我的 request Url
  • 如何将对 System.Data.DataSetExtensions 的引用添加到网站 ascx.cs 文件?

    我们正在处理一个网站项目并尝试参考System Data DataSetExtensions 使用 Web 应用程序会更好 不过 技术主管有她的理由 这是我们尝试过的 找到装配路径 打开 Visual Studio 命令提示符并运行sn e
  • 为什么 C++20 范围不只提供管道语法?

    我知道这个问题听起来很奇怪 所以这里有一些背景信息 最近 我很失望地了解到 C 20 范围内的映射缩减并不像人们所期望的那样工作 即 const double val data transform accumulate 不起作用 你必须这样
  • 验证域用户凭据

    我需要一种方法来验证 Windows 上本机 C 的用户 密码对 输入的是用户名和密码 用户可以是 DOMAIN user 格式 基本上我需要编写一个函数 如果用户 密码是有效的本地帐户 则返回 true 第1部分 如果用户 密码在给定的域
  • PARITY_NONE 是 C++ Windows 中的关键字吗?

    我正在使用 boost 编写一个串行库 并且我有一个枚举 enum parity t PARITY NONE PARITY ODD PARITY EVEN 我收到如下错误 错误 1 错误 C2059 语法错误 我无法弄清楚问题是什么 然后我
  • C 中函数“fgets”的参数太少

    每当我编译这个错误时 我都会收到该错误 但我不知道为什么 我直接从书上抄袭这个 有人可以帮忙吗 include
  • WPF DataGrid 选定项

    我有一个 DataGrid 用户可以通过在最后一行输入数据来添加项目 我还有一个按钮可以删除当前选定的项目 但是 当选择最后一行 空 用于添加新项目 时 最后选定的项目将保留在 SelectedItem 中 因此 如果我打开窗口 选择最后一
  • C# 中的快速字符串解析

    在 C 中解析字符串最快的方法是什么 目前我只是使用字符串索引 string index 并且代码运行合理 但我忍不住认为索引访问器所做的连续范围检查必须添加一些东西 所以 我想知道我应该考虑哪些技术来增强它 这些是我最初的想法 问题 使用
  • File.Move 的原子性

    我想将目录中的文件重命名为原子事务 该文件不会更改目录 该路径作为 NTFS 文件系统的 UNC 路径提供 可能位于服务器 03 或 08 上 File Move 对于这些目的来说是原子的吗 例如 它要么成功完成 要么失败 以使原始文件仍然

随机推荐

  • spring boot jpa + redis LazyInitializationException

    我使用 spring boot 2 1 2 和 redis 作为缓存提供程序 但现在 我有一个问题 在 sysUser 实体中 Data Entity Table name sys user ToString exclude roles E
  • /accounts/signup/ 处出现 SMTPDataError(553,b'不允许以 webmaster@localhost 进行中继')

    我正在使用 Django 1 7 为了进行身份验证 我使用 Django allauth 为了发送电子邮件 我开始使用 zoho smtp 服务器 它能够发送普通邮件和交易邮件 但无法发送注册会话电子邮件 它显示错误 SMTPDataErr
  • 线程“主”java.lang.NoClassDefFoundError 中出现异常:

    以下程序抛出错误 public class HelloWorld public static void main String args System out println Hello World CLASSPATH C Program
  • AS3 合并多个数组的最快方法

    我正在尝试编写一个可以指定任意数量的数组的函数 并且返回值将是一个包含所有指定数组的内容的数组 我已经这样做了 但这似乎是一种非常缓慢且丑陋的方法 var ar1 Array 1 2 3 4 5 6 7 8 9 var ar2 Array
  • 如何截断 STDIN 行长度?

    我一直在解析一些日志文件 发现有些行太长 无法在一行上显示 因此 Terminal app 善意地将它们包装到下一行 但是 我一直在寻找一种在一定数量的字符之后截断一行的方法 以便终端不会换行 从而更容易发现模式 我编写了一个小的 Perl
  • mysql - 多少列太多?

    我正在设置一个可能有 70 列以上的表 我现在正在考虑将其拆分 因为每次访问表时都不需要列中的某些数据 话又说回来 如果我这样做 我就不得不使用联接 在什么时候 如果有的话 被认为列太多 一旦超过了就被认为太多了数据库支持的最大限制 事实上
  • SVG 中的下标和上标

    我正在尝试使用以下代码使用 SVG 显示下标和上标从这个网站
  • Oracle 将列移动到第一个位置

    有没有办法将 Oracle 表中的列从最后一个位置移动到第一个位置 有人删除了 ID 列并重新创建了它 所以现在它到了最后 这是一个问题 因为我们的一些 PHP 脚本使用第一列作为标识符 一个抽象模型以及超过 100 个其他模型使用这个基础
  • 如何在 Google Colaboratory 中以编程方式清除 Python 输出?

    这个问题特定于 Google Colaboratory 虽然某些解决方案可能在普通的 Python 解释器中工作 但 Google Colaboratory 似乎不允许我以编程方式清除 Python 解释器输出 我已经尝试过但不起作用的解决
  • 再次迭代元组...

    我从事 C 工作已经有一段时间了 但我对模板并不熟悉 最近 我尝试编写一个类来包装std vector
  • 进行 json.dump 时如何显式设置回车符?

    我的 python 脚本生成 json 文件 我必须支持这个Python文件在Windows和Linux上工作 问题是windows和linux上的回车符不同 当我在 Windows 上运行此代码时 它输出 CRLF json 当我在 Li
  • Flutter找不到android sdk

    我刚刚尝试安装 flutter 因为我已经安装了 android studio 和 android sdk 所以我只是按照 flutter 的安装进行操作 这是我的问题 当我跑步时 flutter doctor 它告诉我 Flutter C
  • 在 MVC 中处理多个角色 - 基于操作的辅助功能

    我目前有一个项目 我似乎遇到了有关角色的问题 我想我会得到一些关于如何最好地处理该问题的意见 系统将需要可编辑 灵活的角色 不仅控制特定区域的访问 还控制系统功能的使用 添加用户 编辑用户 查看报告等 系统当前允许用户拥有多个角色 每个角色
  • 黑莓 URL 编码器

    我需要在 Blackberry 中使用 HTTP GET 请求对 URL 进行编码 任何人都可以帮助我找到如何实现这一目标 为什么不使用 RIMURL编码的帖子数据 private String encodeUrl String hsURL
  • 如何在TextureView上使用相机预览录制视频

    我一直在一些 Android 4 0 设备上使用TextureView 例如 我尝试开发一个简单的应用程序 它可以录制视频并使用TextureView进行预览 然而 据我阅读Android API文档 标准MediaRecorder需要一定
  • 编织错误。未找到对象

    我有一个未清理的dataset 所以 我已将其导入到我的 R 工作室 然后当我运行时nrow adult 在 rmarkdown 文件中并按ctrl Enter它有效 但是当我按下knit出现以下错误 Answer recommended
  • 处理 DateTime DBNull

    我在 SO 上看到过很多很多版本 但似乎没有一个能完全满足我的需求 我的数据来自供应商数据库 该数据库允许日期时间字段为空 首先 我将数据放入数据表中 using SqlCommand cmd new SqlCommand sb ToStr
  • 使用 vba 将格式化文本复制到 access 中

    我需要将 Word 中的格式化文本保存到 Access 数据库中 到目前为止 我已经设法弄清楚如何在访问字段中存储格式化文本 在表中创建备注字段并将文本格式设置为富文本 搜索SO我还没有找到关于如何将所述文本从word传输到Access的解
  • 为什么百分比填充/边距在 Firefox 和 Edge 中的 Flex 项目上不起​​作用?

    我想在弹性盒内有一个方形 div 所以我用 outer display flex width 100 background blue inner width 50 background yellow padding bottom 50 di
  • 在另一个线程(不是主线程)中创建窗口

    我有一个功能 HWND createMainWindow P2p Socket Machine toSend HWND hMainWnd CreateWindow L Class LPCWSTR nameOfConference c str