2013-02-02 16 views
6

के रूप में करें, मैं एक छोटी कक्षा बनाने की कोशिश कर रहा हूं जो मूल विंडो में कंसोल विंडो प्रदर्शित करता है। (आप कल्पना कर सकते हैं कि वहां चैट या डीबग जानकारी प्रदर्शित की जा रही है)
अब, क्योंकि अलग-अलग इंस्टेंस के पास अलग-अलग निजी चर होते हैं (जैसे संदेश सरणी या पैरेंट विंडो), मुझे विंडोज़ ईवेंट के लिए कॉलबैक के रूप में गैर स्थैतिक विधि का उपयोग करने की आवश्यकता है।
मैंने तरीकों के बारे में सोचा है, जहां मैं वास्तविक कॉलबैक फ़ंक्शन को वास्तविक कॉलबैक फ़ंक्शन पर पास कर दूंगा और फिर उस पर उचित विधि कहूंगा, लेकिन WinAPI में, सब कुछ TranslateMessage और DispatchMessage का उपयोग करके किया जाता है, जिससे मुझे मेरे तर्कों का उपयोग करने का कोई मौका नहीं मिलता है खुद।
मुझे कुछ कोड यहां मिला: Class method as winAPI callback, लेकिन मुझे यह समझ में नहीं आता है, और मुझे लगता है कि यह बिल्कुल वैसा ही नहीं है जो मुझे चाहिए। यदि ऐसा है, तो कृपया मुझे दिए गए कोड का और स्पष्टीकरण दें। 'LRESULT (WindowConsole::) (HWND__ , uint, wParam, lParam)' प्रकार के तर्क 'LRESULT (*) (HWND__, uint, से मेल नहीं खाता:
त्रुटि मैं:ऑब्जेक्ट विधि का उपयोग WinApi WndProc कॉलबैक

त्रुटि WPARAM, LPARAM) '

मुझे नहीं पता कि ब्रैकेट में वह सितारा क्या है, लेकिन यह मेल नहीं खाता है।
और कोड:

class WindowConsole { 
    char messages[255][255]; 
    HWND mainWindow; 
    public: 
    int width; 
    int height; 
    inline HWND create(HWND parent); 
    inline bool update(); 
    inline LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); 
}; 

HWND WindowConsole::create(HWND parent) { 
    HINSTANCE inst = GetModuleHandle (0); 
    WNDCLASSEX wincl; 

    /* The Window structure */ 
    wincl.hInstance = inst; 
    wincl.lpszClassName = "ConsoleClass"; 
    wincl.lpfnWndProc = this->WndProc;  /* This function is called by windows */ 
    /* more WNDCLASSEX crap...*/ 

    mainWindow = CreateWindow (
      /*PARAMS*/ 
    ); 
    ShowWindow(mainWindow,1); 
    return mainWindow; 

} 
bool WindowConsole::update() { 
    return true; 
} 
LRESULT CALLBACK WindowConsole::WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { 
    switch (message)     /* handle the messages */ 
    { 
      /*EVENT crap*/ 
    } 

    return 0; 
} 
+0

999999999 ड्यूप्स – Puppy

+0

ठीक है, उनमें से कोई भी मुझे मदद की। मैंने लंबे समय तक खोज की है और इस समस्या पर बहुत अधिक विषय खोजे हैं, लेकिन मुझे बस समझ में नहीं आया। –

+0

उपयोगकर्ता 16100 ... के उत्तर और msdn-article के लिंक पर एक नज़र डालें ... – Incubbus

उत्तर

9

सामान्य इस आदेश पर कुछ न कुछ है। आपकी व्युत्पन्न कक्षा में, आप "विंडोप्रोक" प्रदान करते हैं जो बेसविंडो में (शुद्ध आभासी) को ओवरराइड करता है। यहां की चाल काफी सरल है: चूंकि आप सीधे पैरामीटर पास नहीं कर सकते हैं, इसलिए आप कक्षा के पते को विंडो के GWLP_USERDATA में संग्रहीत करते हैं, फिर विंडो प्रो में (कोशिश करें) इसे पुनर्प्राप्त करें और व्युत्पन्न क्लास वर्चुअल को कॉल करने के लिए इसका उपयोग करें खिड़की proc।

एक तरफ के रूप में, ध्यान दें कि यह एक स्केच है, एक पूर्ण काम नहीं (इसलिए बोलने के लिए)। यद्यपि इसे संकलित करना चाहिए, नतीजा वास्तव में तब तक काम नहीं करेगा जब तक कि आप यहां मौजूद टुकड़ों की उचित संख्या भरें (उदाहरण के लिए, WNDCLASS संरचना के अन्य फ़ील्ड सबसे स्पष्ट में से केवल एक हैं)।

+0

धन्यवाद, आपके उदाहरण के साथ, मैंने कुछ बनाया, कम से कम, त्रुटियों के बिना संकलित करता है। अब obvions सवाल है: मैं खिड़की की घटनाओं को पकड़ने और उन्हें प्रेषित करने के लिए लूप कहाँ डालूँ? क्या मुझे अपना प्रोग्राम असीमित बनाना है (एक और थ्रेड जोड़ें?)? –

+0

@ टॉमसज़ेटो: संदेश लूप हमेशा अनिवार्य रूप से WinMain में है, जो आमतौर पर विंडो का एक उदाहरण बना देगा, फिर एक संदेश लूप में जाएगा। नहीं, आप आमतौर पर इसे एक अलग थ्रेड में चलाने के लिए नहीं चाहते हैं। –

+0

ठीक है, लेकिन मेरी कक्षा कई खिड़कियां बना सकती है क्योंकि मैं कई उदाहरण बना सकता हूं। तो क्या मुझे WinMain() में उनमें से प्रत्येक के लिए ईवेंट भेजने के लिए, कुछ वैश्विक चर में विंडो हैंडलर (एचडब्ल्यूएनडी) रखना चाहिए? –

4

अन्य सवाल आप केवल करने के लिए जोड़ा आंशिक रूप से लागू होता है।

विंडोप्रोक विधि को स्थैतिक होने की आवश्यकता है। फिर GWLP_USERDATA के साथ CreateWindowLongPtr को दूसरे पैरामीटर के रूप में CreateWindowEx कॉल के बाद कॉल करें और यह तीसरा है। वह वर्ग उदाहरण के साथ एचडब्ल्यूएनडी को जोड़ता है। फिर स्थिर विंडोप्रोक विधि में विंडो कंसोल उदाहरण प्राप्त करने के लिए GetWindowLongPtr (फिर से GWLP_USERDATA के साथ) को कॉल करें जिसे UI ईवेंट प्राप्त हुआ।

बस इतना ही यहां विस्तार से समझाया गया है:

#include <windows.h> 

class BaseWindow { 

    static LRESULT CALLBACK internal_WndProc(HWND hWnd, int msg, WORD wParam, LONG lParam) { 
     BaseWindow *c = (BaseWindow *)GetWindowLong(hWnd,GWLP_USERDATA); 

     if (c == NULL) 
      return DefWindowProc(hWnd, msg, wParam, lParam); 

     return c->WindowProc(hWnd, msg, wParam, lParam); 
    } 

public: 
    virtual int WindowProc(HWND hWnd, int msg, WPARAM wParam, LPARAM lParam) = 0; 

    BaseWindow(HINSTANCE instance) { 
     WNDCLASS window_class = {0}; 
     HWND window; 
     HMENU my_menu; 

     window_class.lpfnWndProc = (WNDPROC)internal_WndProc; 
     /* fill in window_class here */ 
     RegisterClass(&window_class); 

     window = CreateWindow(
      "My Application", "Stupidity", 
      WS_OVERLAPPEDWINDOW, 
      CW_USEDEFAULT, CW_USEDEFAULT, 
      CW_USEDEFAULT, CW_USEDEFAULT, 
      NULL, my_menu, instance, NULL); 

     // save the address of the class as the Window's USERDATA. 
     SetWindowLong(window, GWLP_USERDATA, (long)this); 
    } 
}; 
इस के साथ

, आप BaseWindow से एक वर्ग निकाले जाते हैं:

http://msdn.microsoft.com/en-us/library/windows/desktop/ff381400(v=vs.85).aspx

1

मैं एक साधारण समाधान का उपयोग करता हूं। Winproc एक टेम्पलेट फ़ंक्शन है। संदेश रिसीवर setwindowptr के अंदर है।

यदि रिसीवर के पास संदेश नाम के साथ कोई फ़ंक्शन है, उदाहरण के लिए, ऑनपेंट, तो wm_paint संदेश स्विच पर शामिल किया गया है।

http://www.thradams.com/codeblog/wndproc.htm

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