2012-03-11 17 views
5

मैं एक समारोह मिल गया है:एक और धागा में विंडो बनाना (नहीं मुख्य थ्रेड)

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() मेरे प्रोग्राम के मुख्य भाग में यह काम करता है, लेकिन जब मैं इसे में चलाता हूं तो मेरा धागा (क्लाइंट थ्रेड) यह काम नहीं करता है। मैंने पढ़ा है कि मुझे केवल मुख्य धागे में खिड़कियां बनाना चाहिए। क्या यह सच है? और यदि यह सच है, तो इस फ़ंक्शन को किसी अन्य थैड से मुख्य थ्रेड में करने का सबसे आसान तरीका क्या है?


सभी को धन्यवाद। अब मुझे समस्या पता है, लेकिन मैं समाधान के साथ अटक गया हूँ। मेरे क्लाइंट धागा कोड है:

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() इस सूत्र बंद हो जाता है संदेश प्राप्त करता है जब तक। मैं ज्ञान की कमी के लिए क्षमा चाहता हूं, लेकिन इसका उपयोग करने के लिए मैं कौन से कार्यों का उपयोग कर सकता हूं या किसी अन्य चीज का उपयोग कर सकता हूं। क्या मुझे अपनी विधि को msgByUdp() को एसिंक्रोनस होने के लिए पुनः लिखना चाहिए या मैं मुख्य थ्रेड पर चलाने के लिए फ़ंक्शन कैसे बना सकता हूं। मेन विन्डो() को अंतिम संस्करण के बारे में: मैं इसे शुद्ध winapi में कैसे कर सकता हूं, मुझे कोई आसान उदाहरण नहीं मिला। क्या कोई कोड स्निपेट दे सकता है। धन्यवाद एक और बार)

+0

धन्यवाद हर कोई।मैं इस कार्यक्रम को काम करने में कामयाब रहा। मैंने डेविड हेफरनन द्वारा विधि का उपयोग किया। और इस लिंक पर जानकारी http://stackoverflow.com/questions/7060686/how-do-i-sendmessage-to-a- विन्डो-created-on-another-thread – knightOfSpring

उत्तर

6

आप मुख्य UI थ्रेड के अलावा अन्य धागे में विंडो बना सकते हैं। हालांकि, उन खिड़कियों के पास उस धागे से संबंध होगा जो उन्हें बनाया गया था और आपको विंडोज़ बनाने वाले प्रत्येक थ्रेड में एक संदेश पंप चलाने की आवश्यकता होगी।

तो जब आप जो भी पूछते हैं, वही कर सकते हैं, Win32 वास्तव में एक ही थ्रेड के साथ एक प्रक्रिया में सभी खिड़कियों के साथ काम करने के लिए डिज़ाइन किया गया है। एकाधिक UI थ्रेड बनाने से वास्तव में कुछ भी प्राप्त नहीं किया जा सकता है। आप जो भी करने में सफल होंगे, वह आपके जीवन को असाधारण और अनिवार्य रूप से जटिल बना रहा है।

+0

हां, यह जटिल है। लेकिन मेरी स्थिति में मुझे एक और समाधान नहीं मिल रहा है। गैर-मुख्य थ्रेड सॉकेट में संदेश प्राप्त होते हैं, और जब मुझे विशेष संदेश मिलता है तो मुझे विंडो बनाने की आवश्यकता होती है। मुझे नहीं पता कि इसे मुख्य धागे में कैसे बनाया जाए। मैं winapi में नौसिखिया हूँ, तो शायद आप मुझे बताएंगे कि इस तरह की चाल कैसे करें? – knightOfSpring

+0

यह एक आम परिदृश्य है। आप जो करते हैं वह मुख्य धागे पर संदेश भेजता है या पोस्ट करता है और विंडो बनाने के लिए मुख्य धागा प्राप्त करता है। सभी जीयूआई ढांचे इस परिदृश्य का समर्थन करने के लिए तंत्र प्रदान करते हैं। –

+0

लेकिन अगर मुझे शुद्ध winapi में ऐसा करने की ज़रूरत है? क्या यह बहुत जटिल होगा? – knightOfSpring

3

आप "गैर-मुख्य" धागे पर खिड़कियां बना सकते हैं लेकिन जागरूक रहें कि उन खिड़कियां सृजन धागे से जुड़ी हैं, और आपको वहां एक संदेश लूप को लागू करना और प्रेषण संदेशों को प्रेषित करना सुनिश्चित करना होगा कतार पर यदि आप ऐसा नहीं करते हैं, तो आपकी खिड़कियां स्थिर हो रही हैं।

देखें:

प्रणाली स्वचालित रूप से प्रत्येक थ्रेड के लिए एक संदेश कतार पैदा नहीं करता। इसके बजाए, सिस्टम केवल धागे के लिए एक संदेश कतार बनाता है जो एक संदेश कतार की आवश्यकता वाले संचालन करता है। यदि थ्रेड एक या अधिक विंडो बनाता है, तो एक संदेश लूप प्रदान किया जाना चाहिए; यह संदेश लूप थ्रेड के संदेश कतार से संदेशों को पुनर्प्राप्त करता है और उन्हें उपयुक्त विंडो प्रक्रियाओं में भेजता है।

+0

तो, मुझे बस इतना करना है कि मुझे जोड़ना है संदेशों को प्रेषित करने के लिए मेरे गैर-मुख्य धागे को कोड। लेकिन एक समस्या है: इस धागे में मैं सॉकेट के साथ काम करता हूं, मुझे संदेश प्राप्त होते हैं, और कुछ फ़ंक्शन मेरे लूप को तब तक रोकते हैं जब तक सॉकेट संदेश प्राप्त नहीं करता। मुझे लगता है कि इसे हल करने का एकमात्र तरीका खिड़की से संदेशों को प्रेषित करने के लिए मेरे गैर-मुख्य धागे में एक और धागा बनाना है। तुम क्या सोचते हो? – knightOfSpring

+0

@Roman मेरे विचार में यह सुझाव देना बुरा होगा कि कई यूआई थ्रेड यहां सबसे अच्छा समाधान है। आपकी क्या राय है? क्या आप मुझसे सहमत हैं या नहीं? –

+0

आपके पास सॉकेट के साथ काम करने के लिए एपीआई के विकल्प हैं, आपको केवल उन कॉल को अवरुद्ध करने से बचने की आवश्यकता नहीं है जहां निष्पादन एपीआई के भीतर लंबे समय तक खर्च कर रहा है। –

3

यदि आप किसी अन्य धागे में एक विंडो बनाते हैं, तो आपको उस धागे पर एक संदेश लूप को भी लागू करने की आवश्यकता होगी क्योंकि कतारबद्ध संदेश विंडो के मालिक के धागे की संदेश कतार में पोस्ट किए जाते हैं।

संबंधित मुद्दे