2010-06-23 10 views
8

का आकार बदलता है, मैं एक win32 एप्लिकेशन लिखता हूं। मैंने संदेश लूप को स्वयं इस तरह कार्यान्वित किया:Win32: मेरा एप्लिकेशन फ्रीज करता है जबकि उपयोगकर्ता विंडो

 bool programcontinue = true; 
    while(programcontinue) 
    { 
       while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) 
       { 
         TranslateMessage(&Msg); 
         DispatchMessage(&Msg); 
       } 

       IdleProcess(); 
    } 

मेरे आवेदन में एक आकार बदलने योग्य विंडो है। आमतौर पर, IdleProcess() प्रति सेकेंड कई बार बुलाया जाता है। जब उपयोगकर्ता किसी कोने या आकार बदलने योग्य विंडो के किनारे को पकड़ लेता है, तब तक उपयोगकर्ता को तब तक नहीं कहा जाता जब तक कि उपयोगकर्ता माउस बटन जारी नहीं करता।

यहां क्या होता है?

मैंने आंतरिक के साथ आंतरिक रूप से आदान-प्रदान करने की कोशिश की, लेकिन यह व्यवहार को नहीं बदले। ऐसा लगता है कि आकार बदलने पर शुरू होने पर, उस संदेश के हैंडलर तब तक वापस नहीं आते जब तक आकार बदल नहीं जाता है?

क्या इसे बदलने का कोई तरीका है और प्रति सेकंड कुछ बार आकार बदलने के दौरान IdleProcess() को कॉल करें?

धन्यवाद मार्क

संपादित करें:

क्या मैं भीतरी जबकि जगह के साथ करता है, तो है मतलब:

bool programcontinue = true; 
while(programcontinue) 
{ 
      if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) // <<<< 
      { 
        TranslateMessage(&Msg); 
        DispatchMessage(&Msg); 
      } 

      IdleProcess(); 
} 

मेरे खिड़की प्रोक थोड़ा लंबा है, लेकिन मैं समान व्यवहार प्राप्त एक छोटे से टेस्ट ऐप के साथ।

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    int wmId, wmEvent; 
    PAINTSTRUCT ps; 
    HDC hdc; 

    switch (message) 
    { 
    case WM_COMMAND: 
     wmId = LOWORD(wParam); 
     wmEvent = HIWORD(wParam); 
     // Parse the menu selections: 
     switch (wmId) 
     { 
     case IDM_ABOUT: 
      DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 
      break; 
     case IDM_EXIT: 
      DestroyWindow(hWnd); 
      break; 
     default: 
      return DefWindowProc(hWnd, message, wParam, lParam); 
     } 
     break; 
    case WM_PAINT: 
     hdc = BeginPaint(hWnd, &ps); 
     // TODO: Add any drawing code here... 
     EndPaint(hWnd, &ps); 
     break; 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
    } 
    return 0; 
} 
+0

क्या आप अपनी WndProc (...) विंडो प्रक्रिया पोस्ट कर सकते हैं जो डिस्पैच मैसेज() से संदेशों को प्राप्त करेगा क्योंकि थोड़ी उत्सुकता –

+0

पूर्ण होने के बारे में आपकी टिप्पणी के बाद + "if" के बजाय " जबकि "चीज। – marc40000

+0

अद्यतन के आधार पर यह है कि या तो TranslateMessage या DispatchMessage तुरंत नहीं लौटा रहा है स्पष्ट है। आपका अगला कार्य यह पता लगाने के लिए है कि कौन सा, और कौन सा संदेश इसे ट्रिगर कर रहा है। –

उत्तर

14

विंडोज़ पर होने वाले कई मोडल ऑपरेशंस हैं। Win32 मॉडल ऑपरेशंस उन कार्यों को संदर्भित करता है जो मोड को समाप्त होने तक अपना स्वयं का ईवेंट प्रसंस्करण पाश शुरू करके "मोड" में एप्लिकेशन डालते हैं। सामान्य अनुप्रयोग मोड में ड्रैग और ड्रॉप ऑपरेशंस, चाल/आकार संचालन शामिल होते हैं, कभी भी एक संवाद पॉप अप होता है जिसे एप्लिकेशन जारी रखने से पहले इनपुट की आवश्यकता होती है।

तो क्या हो रहा है: आपका संदेश लूप नहीं चल रहा है। आपकी विंडो ने एक WM_LBUTTONDOWN संदेश प्राप्त किया जिसे आपने DefWindowProc को पास किया था। DefWindowProc ने निर्धारित किया कि उपयोगकर्ता आकार को आकार देने या विंडो को अंतःक्रियात्मक रूप से स्थानांतरित करने का प्रयास कर रहा था और आकार बदलने/चलने वाले मोडल फ़ंक्शन में प्रवेश कर रहा था। यह फ़ंक्शन एक संदेश प्रसंस्करण लूप में है जो माउस संदेशों के लिए देख रहा है ताकि यह उन्हें इंटरैक्टिव आकार देने का अनुभव प्रदान करने में बाधित कर सके, और जब आकार का संचालन पूरा हो जाए तो केवल बाहर निकल जाएगा - आम तौर पर उपयोगकर्ता द्वारा आयोजित बटन को जारी करने या भागने से दबाकर।

आपको इस बारे में अधिसूचित किया जाता है - DefWindowProc एक WM_ENTERSIZEMOVE और WM_EXITSIZEMOVE संदेशों को भेजता है क्योंकि यह मोडल इवेंट प्रोसेसिंग लूप में प्रवेश करता है और बाहर निकलता है।

"निष्क्रिय" संदेश उत्पन्न करना जारी रखने के लिए, आमतौर पर एक मोडल फ़ंक्शन को कॉल करने से पहले टाइमर (सेटटाइमर) बनाएं - या जब एक संदेश प्राप्त हो रहा है कि DefWindowProc एक मोडल फ़ंक्शन में प्रवेश कर रहा है - मोडल लूप WM_TIMER संदेशों को प्रेषित करना जारी रखेगा .. और टाइमर संदेश हैंडलर से निष्क्रिय प्रो को कॉल करें।मोडल फ़ंक्शन लौटाते समय टाइमर को नष्ट करें।

1

आकार विंडोज के दौरान अपने कार्यक्रम के लिए काफी कुछ संदेश भेजता है: यह wndproc वी.एस. परियोजना जादूगर बनाता है के समान है। मैंने यह साबित नहीं किया है, लेकिन आपके द्वारा वर्णित व्यवहार परिचित है। हालांकि कि यह मान लिया गया है

bool programcontinue = true; 
while(programcontinue) 
{ 
      while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) 
      { 
        TranslateMessage(&Msg); 
        DispatchMessage(&Msg); 
        if(Msg.message == WM_SIZING) 
         IdleProcess(); 
      } 

      IdleProcess(); 
} 

ध्यान रखें: मैं भी इस तरह के WM_SIZING के रूप में कुछ घटनाओं के लिए है, जबकि (...) लूप के अंदर) के अपने कार्य IdleProcess (कॉल करने के लिए जो आपके आवेदन खिड़की का आकार बदलने के दौरान अक्सर प्राप्त होगा सुझाव देंगे , कि IdleProcess() किसी भी घटना का निर्माण या उपभोग नहीं करता है। यदि मामला है, तो चीजें अधिक जटिल हो जाती हैं।

+0

इससे मदद नहीं मिलती है। जैसा कि मैंने अपने प्रश्न में लिखा था "मैंने आंतरिक के साथ आंतरिक रूप से आदान-प्रदान करने की कोशिश की" – marc40000

4

जब DefWindowProc WM_SYSCOMMAND को WMaram में SC_MOVE या SC_SIZE के साथ संभालता है, तो यह एक लूप में प्रवेश करता है जब तक कि उपयोगकर्ता माउस बटन को छोड़कर या तो प्रवेश या भागने से रोकता है। यह इस करता है क्योंकि यह कार्यक्रम WM_PAINT और WM_NCPAINT संदेशों को संभालने (आप अभी भी अपने विंडो प्रक्रिया में इन घटनाओं प्राप्त करना चाहिए) द्वारा दोनों ग्राहक क्षेत्र (जहां आपकी विजेट या खेल या जो कुछ भी तैयार की है) और सीमाओं और कैप्शन क्षेत्र रेंडर करने के लिए अनुमति देता है।

यह सामान्य विंडोज क्षुधा, जो उनके विंडो प्रक्रिया के अंदर अपनी प्रसंस्करण के सबसे अधिक है संदेशों को प्राप्त करने का एक परिणाम के रूप में के लिए ठीक काम करता है। यह केवल उन कार्यक्रमों को प्रभावित करता है जो विंडो प्रक्रिया के बाहर प्रसंस्करण करते हैं, जैसे गेम (जो आमतौर पर पूर्णस्क्रीन होते हैं और वैसे भी प्रभावित नहीं होते हैं)।

हालांकि, इसके चारों ओर एक रास्ता है: स्वयं को WM_SYSCOMMAND को संभालें, आकार बदलें या स्वयं को ले जाएं। इसके लिए प्रयासों का एक अच्छा सौदा की आवश्यकता है, लेकिन यह इसके लायक साबित हो सकता है। वैकल्पिक रूप से, आप विंडो प्रक्रिया से बचने के लिए जब WM_SIZING भेज दिया जाता है, या Windows रेशे उसी तर्ज पर setjmp/longjmp इस्तेमाल कर सकते हैं; हालांकि ये हैकिश समाधान हैं।

मैं इसे हल यह पिछले सप्ताह के अंत में (पहली विधि का उपयोग कर), यदि आप मैं sourceforge पर सार्वजनिक डोमेन के लिए कोड जारी किया है रुचि रखते हैं। बस रीडमे, विशेष रूप से चेतावनी अनुभाग को पढ़ना सुनिश्चित करें। संदेश यह है: https://sourceforge.net/projects/win32loopl/

1

तुम अब भी WM_PAINT संदेश प्राप्त कर सकते हैं, तो आप सिर्फ होगा WinAPI आप चाहते हैं कि यह (NeHe ओपन ट्यूटोरियल में देखा) बता:

windowClass.style   = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraws The Window For Any Movement/Resizing 

यह अभी भी अपने while/PeekMessage को अवरुद्ध कर देगा हालांकि! WinAPI सिर्फ आपके WndProc को सीधे कॉल करता है।