2012-03-10 13 views
5

के साथ विफल रहता है मेरे पास कई कस्टम नियंत्रण वाले प्रोग्राम हैं। इन कस्टम नियंत्रणों में से एक एक पाठ इनपुट नियंत्रण है। चूंकि जब आप उस पर क्लिक करते हैं तो विंडो स्वचालित रूप से कीबोर्ड फ़ोकस प्राप्त नहीं करती है, इसलिए मैंने अपने प्रोग्राम में एक माउस हुक बनाया है जो उस विंडो में क्लिक करते समय विंडो पर SetFocus() को कॉल करता है। हालांकि, वहाँ एक समस्या है।SetFocus() वैध विंडो हैंडल

यदि कोई अन्य प्रोग्राम फोकस करता है जब आप मेरे प्रोग्राम की विंडो (या उस विंडो में से किसी भी नियंत्रण) पर क्लिक करते हैं तो SetFocus() विफल रहता है। इसके बाद मुझे सफल होने के लिए फिर से क्लिक करना होगा।

SetFocus(Hwnd = 00410c06) failed. Error code: 87 
SetFocus(Hwnd = 00410c06) returned success. 
SetFocus(Hwnd = 01740fc8) failed. Error code: 87 
SetFocus(Hwnd = 01740fc8) returned success. 

त्रुटि कोड 87 ERROR_INVALID_PARAMETER है, लेकिन मैं स्पष्ट रूप से कार्य करने के लिए एक वैध खिड़की संभाल गुजर रहा हूँ, तो क्यों:

LRESULT CALLBACK kbfProc(int nCode, WPARAM wParam, LPARAM lParam) // Keyboard focus switching procedure 
{ 
    switch(nCode) 
    { 
     case HC_ACTION: 
     { 
      if(wParam == WM_LBUTTONDOWN || wParam == WM_NCLBUTTONDOWN) 
      { 
       MOUSEHOOKSTRUCT * mhs = (MOUSEHOOKSTRUCT*) lParam; 

       if(SetFocus(mhs->hwnd) == NULL) 
       { 
        printf("SetFocus(Hwnd = %.8x) failed. Error code: %lu\n", mhs->hwnd, GetLastError()); 
       } else { 

        printf("SetFocus(Hwnd = %.8x) returned success.\n", mhs->hwnd); 
       } 
      } 

     } 
     break; 
    } 

    return CallNextHookEx(0, nCode, wParam, lParam); 
} 

और उन printf कॉल के उत्पादन में इस है: कोड यह क्या यह असफल रहा है?

+0

जब भी माउस चलता है तो आपका केबीएफप्रोक कॉलबैक विधि माना जाता है? हमें WINAPI विधि पर कॉल दिखाएं। इसके अलावा, मुझे लगता है कि एक फॉर्म लोड इवेंट के माध्यम से फोकस सेट करना बेहतर है। –

+0

@opatachibueze WINAPI विधि? फॉर्म लोड इवेंट? क्या वह .NET से नहीं है? मैं सी ++ का उपयोग कर रहा हूं ... – Gogeta70

+0

आपके कोड का कौन सा हिस्सा LRESULT CALLBACK KbfProc –

उत्तर

1

मुझे समाधान मिला है। मैं बहुत सारी चीजें कर रहा हूं और कई अलग-अलग चीजों की कोशिश कर रहा हूं, और अंत में मैं this वेबपृष्ठ पर आया। यह एक लंबा पठन है और यह थोड़ा सा शब्द और समझने में मुश्किल है, लेकिन इसमें बहुत सारी जानकारी है। मैंने अपनी मुख्य विंडो के WM_ACTIVATE हैंडलर में कुछ कोड जोड़ना समाप्त कर दिया जो विंडो विंडो सक्रिय होने पर क्लिक की गई बाल विंडो की खोज करता है।

यहाँ हुक प्रक्रिया है:

LRESULT CALLBACK kbfProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    switch(nCode) 
    { 
     case HC_ACTION: 
     { 
      if(wParam == WM_LBUTTONDOWN || wParam == WM_NCLBUTTONDOWN) 
      { 
       MOUSEHOOKSTRUCT * mhs = (MOUSEHOOKSTRUCT*) lParam; 

       BringWindowToTop(MainWindow->t_hwnd); 
       SetFocus(mhs->hwnd); 
      } 

     } 
     break; 
    } 

    return CallNextHookEx(0, nCode, wParam, lParam); 
} 

यहाँ कोड मैं WM_ACTIVATE हैंडलर में डाल दिया गया है: यहाँ सब कोड है

case WM_ACTIVATE: 
    { 
     unsigned long state = (unsigned long) wParam & 0x0000FFFF; 
     unsigned long mState = (unsigned long) wParam & 0xFFFF0000; 

     if(state != 0) 
     { 
      ...[some code here]... 

      FocusChildWindow(hwnd); 
     } 

     ...[some code here]... 
    } 
    break; 

और यहाँ है FocusChildWindow() फ़ंक्शन:

void FocusChildWindow(HWND hwnd) 
{ 
    POINT mpos; 
    GetCursorPos(&mpos); 

    RECT wr; 
    GetWindowRect(hwnd, &wr); 

    mpos.x -= wr.left; 
    mpos.y -= wr.top; 

    HWND cw = ChildWindowFromPoint(hwnd, mpos); 

    if(cw == NULL || cw == hwnd) 
    { 
     SetFocus(hwnd); 
    } else { 

     GetCursorPos(&mpos); 
     HWND cw2; 

     while(1) 
     { 
      POINT sc = mpos; 
      MapWindowPoints(HWND_DESKTOP, cw, &sc, 1); 

      cw2 = ChildWindowFromPoint(cw, sc); 

      if(cw2 == NULL || cw2 == cw) 
      { 
       SetFocus(cw); 
       break; 
      } else { 

       cw = cw2; 
      } 


     } 

    } 

} 

यह एक आकर्षण की तरह काम करता है। इस समस्या पर आपके इनपुट और विचारों के लिए सभी को फिर से धन्यवाद।

3

जब भी आप सेटफोकस को कॉल कर रहे हों, तो विंडो को कॉलिंग थ्रेड के संदेश कतार से जोड़ा जाना चाहिए या सेटफोकस अमान्य वापस आ जाएगा यदि यह नहीं है। इसे काम करने के लिए, पर कॉल करने से पहले माउस आपकी विंडो पर आगे बढ़ने पर SetForegroundWindow का उपयोग करें।

+0

मैंने कोशिश की आपका सुझाव, लेकिन मुझे अभी भी एक ही परिणाम मिल रहा है। – Gogeta70

+0

हम्म, सेटफोकस का रिटर्न वैल्यू क्या होता है जब यह दो मामलों में सफल होता है? इसे उस विंडो को वापस करना चाहिए जिसमें पिछले फोकस था। साथ ही, क्या आपने 'SetActiveWindow'' की कोशिश की है? –

+0

क्या आपने 'अटैच थ्रेड इनपुट (GetWindowThreadProcessId (विंडो), GetCurrentThreadId(), सत्य की कोशिश की है? –

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