2010-02-12 6 views
17

मेरा ऐप। सिस्टम पर चल रहा है एक हॉटकी के लिए निगरानी की कोशिश; जब उपयोगकर्ता किसी भी विंडो में कुछ टेक्स्ट चुनता है और हॉटकी दबाता है, तो मुझे चयनित टेक्स्ट कैसे प्राप्त होता है, जब मुझे WM_HOTKEY संदेश मिलता है?देशी Win32 API का उपयोग कर केंद्रित विंडो से चयनित टेक्स्ट कैसे प्राप्त करूं?

क्लिपबोर्ड पर पाठ पर कब्जा करने के लिए, मैं सक्रिय विंडो (GetActiveWindow()) और forground विंडो (GetForegroundWindow()) को keybd_event() और SendInput() का उपयोग कर Ctrl + C भेजने की कोशिश की, इनके बीच संयोजन की कोशिश की; सब व्यर्थ। क्या मुझे सादे Win32 सिस्टम एपीआई के साथ विंडोज़ में फोकस विंडो का चयनित टेक्स्ट मिल सकता है?

+1

क्या आप वाकई सही विंडो हैंडल प्राप्त कर रहे हैं? आप Spy ++ के साथ इसका परीक्षण कर सकते हैं। साथ ही, क्या आपने पुराने पुराने WM_GETTEXT को आजमाया है? – Luke

+0

कौन सा विंडोज संस्करण? –

+0

@Aaron: विंडोज एक्सपी और बाद में; 32 और 64 दोनों बिट्स; मूल रूप से विंडोज़ में अपना ऐप (http://artha.sourceforge.net/) पोर्ट कर रहा हूं और मुझे आगे बढ़ने के लिए इस सुविधा की आवश्यकता है। – legends2k

उत्तर

19

टीएल; डीआर: हां, सादे Win32 सिस्टम एपीआई का उपयोग करके ऐसा करने का एक तरीका है, लेकिन इसे सही ढंग से कार्यान्वित करना मुश्किल है।

WM_COPY और WM_GETTEXT काम कर सकते हैं, लेकिन सभी मामलों में नहीं। वे सही तरीके से अनुरोध को संभालने वाली प्राप्त करने वाली विंडो पर निर्भर करते हैं - और कई मामलों में यह नहीं होगा। मुझे ऐसा करने के एक संभावित तरीके से भागने दो। यह उतना आसान नहीं हो सकता जितना आप उम्मीद कर रहे थे, लेकिन Win32 प्रोग्रामिंग की साहसिक भरे दुनिया में क्या है? तैयार? ठीक। चलिए चलते हैं।

सबसे पहले हमें लक्ष्य विंडो की HWND आईडी प्राप्त करने की आवश्यकता है। ऐसा करने के कई तरीके हैं। ऐसा एक दृष्टिकोण है जिसे आपने उपर्युक्त बताया है: फोरग्राउंड विंडो प्राप्त करें और फिर फोकस के साथ खिड़की प्राप्त करें। हालांकि, एक विशाल गोटाचा है कि कई लोग भूल जाते हैं। फोकस के साथ विंडो प्राप्त करने के लिए आपको अग्रभूमि विंडो प्राप्त करने के बाद AttachThreadInput होना चाहिए। अन्यथा GetFocus() बस NULL वापस आ जाएगा।

एक बहुत आसान तरीका है। बस (मिस) GUITREADINFO कार्यों का उपयोग करें। यह अधिक सुरक्षित है, क्योंकि यह आपके इनपुट थ्रेड को किसी अन्य प्रोग्राम से जोड़ने के साथ जुड़े सभी छिपे खतरों से बचाता है।

LPGUITHREADINFO lpgui = NULL; 
HWND target_window = NULL; 

if(GetGUIThreadInfo(NULL, lpgui)) 
    target_window = lpgui->hwndFocus; 
else 
{ 
    // You can get more information on why the function failed by calling 
    // the win32 function, GetLastError(). 
} 

कॉपी करने के लिए पाठ में थोड़ा और अधिक शामिल है कीस्ट्रोक्स भेजा जा रहा है ...

हम यह तेजी से है, क्योंकि SendInput keybd_event के बजाय का उपयोग करने के लिए जा रहे हैं, और, सबसे महत्वपूर्ण बात, द्वारा में गड़बड़ नहीं किया जा सकता समवर्ती उपयोगकर्ता इनपुट, या अन्य प्रोग्राम keystrokes अनुकरण।

इसका मतलब यह है कि कार्यक्रम को Windows XP या बाद में चलाने की आवश्यकता होगी, हालांकि, क्षमा करें यदि आपका 98 चल रहा है!

// We're sending two keys CONTROL and 'V'. Since keydown and keyup are two 
// seperate messages, we multiply that number by two. 
int key_count = 4; 

INPUT* input = new INPUT[key_count]; 
for(int i = 0; i < key_count; i++) 
{ 
    input[i].dwFlags = 0; 
    input[i].type = INPUT_KEYBOARD; 
} 

input[0].wVK = VK_CONTROL; 
input[0].wScan = MapVirtualKey(VK_CONTROL, MAPVK_VK_TO_VSC); 
input[1].wVK = 0x56 // Virtual key code for 'v' 
input[1].wScan = MapVirtualKey(0x56, MAPVK_VK_TO_VSC); 
input[2].dwFlags = KEYEVENTF_KEYUP; 
input[2].wVK = input[0].wVK; 
input[2].wScan = input[0].wScan; 
input[3].dwFlags = KEYEVENTF_KEYUP; 
input[3].wVK = input[1].wVK; 
input[3].wScan = input[1].wScan; 

if(!SendInput(key_count, (LPINPUT)input, sizeof(INPUT))) 
{ 
    // You can get more information on why this function failed by calling 
    // the win32 function, GetLastError(). 
} 

वहां। वह इतना बुरा नहीं था, है ना?

अब हमें क्लिपबोर्ड में क्या है पर एक झांक लेना है। यह उतना आसान नहीं है जितना आप पहले सोचेंगे। "क्लिपबोर्ड" वास्तव में एक ही चीज़ के कई प्रस्तुतिकरण रख सकता है। जब आप क्लिपबोर्ड पर प्रतिलिपि करते हैं तो सक्रिय है कि क्लिपबोर्ड में वास्तव में क्या स्थान रखना है।

जब आप माइक्रोसॉफ्ट ऑफिस से टेक्स्ट कॉपी करते हैं, उदाहरण के लिए, यह उसी पाठ के सादे-पाठ प्रतिनिधित्व के साथ क्लिपबोर्ड में आरटीएफ डेटा रखता है। इस तरह आप इसे वर्डपैड और नोटपैड में पेस्ट कर सकते हैं। वर्डपैड समृद्ध-पाठ प्रारूप का उपयोग करेगा, जबकि नोटपैड सादे-पाठ प्रारूप का उपयोग करेगा।

इस सरल उदाहरण के लिए, मान लीजिए कि हम केवल सादे टेक्स्ट में दिलचस्पी रखते हैं।

if(OpenClipboard(NULL)) 
{ 
    // Optionally you may want to change CF_TEXT below to CF_UNICODE. 
    // Play around with it, and check out all the standard formats at: 
    // http://msdn.microsoft.com/en-us/library/ms649013(VS.85).aspx 
    HGLOBAL hglb = GetClipboardData(CF_TEXT); 
    LPSTR lpstr = GlobalLock(hglb); 

    // Copy lpstr, then do whatever you want with the copy. 

    GlobalUnlock(hglb); 
    CloseClipboard(); 
} 
else 
{ 
    // You know the drill by now. Check GetLastError() to find out what 
    // went wrong. :) 
} 

और वहां आपके पास है! बस सुनिश्चित करें कि आप कुछ चर के लिए lpstr की प्रतिलिपि बनाते हैं जिसे आप उपयोग करना चाहते हैं, सीधे lpstr का उपयोग न करें, क्योंकि हमें इसे बंद करने से पहले क्लिपबोर्ड की सामग्री को नियंत्रित करना होगा।

Win32 प्रोग्रामिंग पहली बार काफी चुनौतीपूर्ण हो सकता है, लेकिन थोड़ी देर बाद ... यह अभी भी चुनौतीपूर्ण है।

चीयर्स!

+0

सबसे पहले, इस तरह के विस्तृत उत्तर देने के लिए समय निकालने के लिए बहुत कुछ धन्यवाद, बारीकियों को समझाते हुए! मैं कोशिश करूँगा और आपसे वापस आऊंगा। – legends2k

+0

यह सब सामान है जो मुझे कम-स्तरीय कीबोर्ड हुक से जुड़ी पिछली परियोजनाओं में पहले से गुज़रना पड़ा था। अधिकांशतः उन परियोजनाओं से प्रतिलिपि/पेस्ट किया गया और कुछ वर्णनात्मक पाठ जोड़ा गया। आशा करता हूँ की ये काम करेगा! – kurige

+1

यह काम किया! ओह धन्यवाद, एक लंबे समय के बाद, यह अंततः काम किया! इससे पहले जब मैंने SendInput का उपयोग करने का प्रयास किया था, वही कर रहा था, लेकिन समस्या यह थी कि मैंने जिस हॉटकी के लिए पंजीकरण किया था। मैंने 'Ctrl + Alt + S' के लिए पंजीकृत किया है और _WM_HOTKEY_ में, मैंने SendInput को 'Ctrl + C' के साथ बुलाया है। लेकिन जब उपयोगकर्ता 'Ctrl + Alt + S' दबाता है, तो' Alt' अभी भी नीचे जाएगा जब मैं वर्चुअल रूप से 'Ctrl + C' पास करता हूं; जब मैंने हॉटकी को 'विंडोज + एस' में बदल दिया तो यह पूरी तरह से काम करता था। संयोजन में 'Alt' के साथ हॉटकी में, जब मैं वर्चुअल रूप से' Alt' (KEYEVENTF_KEYUP) को दबाता हूं, तो यह भी काम करता है। – legends2k

0

SendMessage (WM_COPY, आदि) आज़माएं।

+0

मैंने यह भी कोशिश की :( – legends2k

3

प्रत्येक SendInput() के बाद Sleep() जोड़ने का प्रयास करें। कुछ ऐप्स बस कीबोर्ड इनपुट को पकड़ने में तेज़ नहीं हैं।

+0

यह कुरिगे के उत्तर के संयोजन में इसे काम करने के लिए बनाया गया! धन्यवाद :) – legends2k

+0

हाँ, उदाहरण के लिए क्रोम डालने में असमर्थ था मेरी प्रक्रिया को पढ़ने से पहले क्लिपबोर्ड में चयनित टेक्स्ट। –

+3

लेकिन अगर आप क्लिपबोर्ड श्रृंखला में अपनी विंडो पंजीकृत करते हैं, तो शायद बेहतर होगा, और अपने ऐप WndProc में WM_DRAWCLIPBOARD जोड़ें। इस तरह आपको खिड़की के बाद संदेश प्राप्त होगा जो इनपुट प्राप्त करता है क्लिपबोर्ड को संशोधित करता है। –

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