হ্যান্ডলিং কীবোর্ড এবং মাউস ইনপুট (Win API)


11

উইন্ডোজ এর অধীনে মাউস বা কীবোর্ড ধরার বিভিন্ন উপায় রয়েছে। তাই আমি তাদের কয়েকটি চেষ্টা করেছিলাম তবে তাদের প্রত্যেকেরই কিছু সুবিধা এবং ত্রুটি রয়েছে। আমি আপনাকে জিজ্ঞাসা করতে চাই: কোন পদ্ধতিটি ব্যবহার করবেন?

আমি এগুলি চেষ্টা করেছি:

  1. WM_KEYDOWN / WM_KEYUP - প্রধান অসুবিধা হ'ল আমি বাম এবং ডান হাতের কীগুলির মধ্যে যেমন ALT, নিয়ন্ত্রণ বা শিফটের মধ্যে পার্থক্য করতে পারি না।

  2. গেটকিবোর্ডস্টেট - এটি প্রথম পদ্ধতির সমস্যাটি সমাধান করে তবে নতুন একটি সমস্যা রয়েছে। যখন আমি পেয়েছি যে ডান-এএলটি কী টিপছে, তখন আমি বাম-নিয়ন্ত্রণ কীটি নীচে রয়েছে তাও পেয়ে যাই। স্থানীয় কীবোর্ড লেআউট (চেক - সিএস) ব্যবহার করার সময় এই আচরণটি ঘটে happens

  3. ডাব্লুএমএনপুট (কাঁচা ইনপুট) - এই পদ্ধতিটি বাম এবং ডান-হাতের কীগুলিতেও পার্থক্য করে না (যদি আমি মনে করতে পারি) এবং মাউস চলাচলের জন্য মাঝেমধ্যে মাউস পজিশনের শূন্য বদ্বীপ মান সহ বার্তা উত্পন্ন করে।

উত্তর:


10

এটি করার সর্বোত্তম ও সিম্পল উপায় হ'ল আপনার প্রথম ধারণাটি ব্যবহার করা এবং ডাব্লুএম_কেইইইউপি / ডাব্লুএম_কেইডাউন বার্তা পাশাপাশি ডাব্লুএমএসওয়াইস্কিওয়াইপ / ডাব্লুএমএসওয়াইস্কিওয়াইডাউন বার্তা হ্যান্ডেল করা। এগুলি বাম এবং ডান শিফট / নিয়ন্ত্রণ / Alt কীগুলির মধ্যে পার্থক্য সনাক্ত করতে পারে, আপনার কেবল উপযুক্ত ভার্চুয়াল কী কোডগুলি দরকার । এগুলি হলেন ভি কে_এলএসএইচআইএফটি / ভিকে_আরএসআইএফটি, ভিকে_এলসিএন্ট্রোল / ভিকে_আরসিএনট্রোল এবং ভিকে_এলএমএনইউ / ভিকে_আরমেনু (ALT কীর জন্য)।

আমি কীভাবে এটি করেছি সে সম্পর্কে একটি পোস্ট লিখেছিলাম এবং আমি একই হ্যান্ডলারে WM_KEYUP / WM_KEYDOWN এবং WM_SYSKEYUP / WM_SYSKEYDOWN উভয়ই পরিচালনা করছি। (দুর্ভাগ্যক্রমে, ব্লগটি আর উপলব্ধ নেই))

কেবলমাত্র জটিলতাটি আমি দেখতে পাচ্ছি তা হ'ল আপনি ইউএস-নন-কীবোর্ড ব্যবহার করছেন কারণ এমএসডিএন- এ ডাব্লুএমএসওয়াইএসকেইইইউপি নিবন্ধে বর্ণিত ক্রমটি পরিচালনা করতে আপনাকে কিছু অতিরিক্ত যুক্তি যুক্ত করতে হবে । তবে আমি সম্ভবত মাস্টারোডিয়ার চেয়ে সহজ কিছু করার চেষ্টা করব।


ডাব্লুএম_স বার্তাগুলি অবশ্যই সহজতম, তবে "সেরা" কেবলমাত্র যদি আপনি মিস করা ইভেন্টগুলির বিষয়ে চিন্তা না করেন। আমি বুঝতে পারলাম যে এটি একটি জটিল সমস্যা ছিল; যদি আপনার অ্যাপ্লিকেশনটি কোনও কীটি নিচে থাকাকালীন ফোকাস হারায়, আপনি কীটিকে আবার ফোকাস না করে অবধি এই কীটি "আটকে" থাকবে।
ড্যাশ-টম-ব্যাং

1
প্রকৃতপক্ষে অনুপস্থিত হওয়া একটি সমস্যা, তবে সবচেয়ে সহজ সমাধান হ'ল ফোকাস / অ্যাক্টিভেশন বার্তাগুলি যথাযথভাবে পরিচালনা করা এবং এর চারপাশে কাজ করা। ব্যবহারিকভাবে আপনি যা করতে চান তা হ'ল গেমটি বিরতি দেওয়া যখন আপনি ফোকাস হারিয়ে ফেলেন, যেহেতু ব্যবহারকারীর অন্য কোনও জরুরি অ্যাপ্লিকেশনটিতে স্যুইচ করা দরকার হতে পারে, বা তারা ঘটনাক্রমে উইন্ডোজ কীতে আঘাত করে।
দেমিন

3

আপনি কি তাদের একত্রিত করতে পারবেন না এমন কোনও কারণ আছে? উদাহরণস্বরূপ, কোনও সিটিআরএল / আল্ট / শিফট কী টিপতে সনাক্ত করতে WM_KEYDOWN ব্যবহার করুন, তারপরে এই কলটির মধ্যে ডান থেকে বাম পার্থক্য করার জন্য গেটকিবোর্ডস্টেট () ব্যবহার করুন?


হ্যা আমি পারি. আমি সম্ভবত এই সমাধানটি দিয়ে শেষ করব (সম্ভবত GetAsyncKeyState ব্যবহার করা ভাল)। তবে আমি উপস্থিত থাকলে আরও ভাল সমাধানের সন্ধান করছি। এবং ডান-এটিএল কী দুটি ডাব্লুএম_কেডাউন বার্তাও উত্পন্ন করে (কীবোর্ড বিন্যাসের কারণে)। সুতরাং কেবল ডাব্লুএমপিপুট বা ডাইরেক্টইনপুট রয়ে গেছে।
ডিলাক্স

3

ডাব্লুএমপিপুট দুর্দান্ত। আমি মনে করি আপনি RAWKEYBOARD স্ট্রাক্ট ব্যবহার করে বাম / ডান কীগুলি আলাদা করতে পারবেন । শক্ত অংশটি কী কী শনাক্তকারীদের (যেমন স্ক্যানকোডগুলি) মোকাবেলা করতে পারে তা নির্ধারণ করতে পারে, তবে আমি বলতে পারি না যেহেতু আমি কীবোর্ড ইনপুটটির জন্য এটি ব্যবহার করার চেষ্টা করিনি। WM_KEYDOWN এত সহজ :)

যদিও আমি মাউস ইনপুট জন্য ডাব্লুএমএনপুট ব্যবহার করেছি। এটি খুব নিম্ন স্তরের এটিতে কোনও ত্বরণ প্রয়োগ করা হয়নি যা খুব সুন্দর (আইএমও)। উচ্চ-ডিপিআই মাউস চলাচলের সুবিধা নেওয়ার একমাত্র উপায় ডাব্লুএমএনপুট ছিল, তবে আমি এখনও নিশ্চিত না যে এটি এখনও ঘটেছে কিনা। 2006 থেকে এই এমএসডিএন নিবন্ধটি দেখুন ।

মাউস / কীবোর্ডের জন্য ডাইরেক্টইনপুট মাইক্রোসফ্ট দ্বারা স্পষ্টভাবে নিরুৎসাহিত করা হয়েছে। পূর্বে লিঙ্কযুক্ত এমএসডিএন নিবন্ধটি দেখুন। আপনার যদি জয়স্টিকের প্রয়োজন হয় তবে এক্সআইএনপুট সম্ভবত এটিই যাবেন।

সম্পাদনা: এটি সম্পর্কে আমার তথ্য খুব তারিখ হতে পারে।


3

আসলে, আপনি যখন ডাব্লুএম_কেইডাউন / ডাব্লুএম_কিওয়াপ ধরেন তখন আপনি L / R Ctrl / Alt কে আলাদা করুন apart সহজ, এটি নয়, তবে আমি যে কোডটি ব্যবহার করি তা এখানে আপনি করতে পারেন, হুঁ হুঁ।

আশা করি এটি এখনও কার্যকর হয়, আমি করি।

// Receives a WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN or WM_SYSKEYUP message and 
// returns a virtual key of the key that triggered the message.
// 
// If the key has a common virtual key code, that code is returned. 
// For Alt's and Ctrl's, the values from the KeyCodes enumeration are used.
int translateKeyMessage (MSG& Msg);

// Virtual key codes for keys that aren't defined in the windows headers.
enum KeyCodes
{
    VK_LEFTCTRL = 162,
    VK_RIGHTCTRL = 163,
    VK_LEFTALT = 164,
    VK_RIGHTALT = 165
};

// ======================================================================================

int translateKeyMessage (MSG& Msg)
{
    // Determine the virtual key code.
    int VirtualKeyCode = Msg.wParam;

    // Determine whether the key is an extended key, e.g. a right 
    // hand Alt or Ctrl.
    bool Extended = (Msg.lParam & (1 << 24)) != 0;

    // If this is a system message, is the Alt bit of the message on?
    bool AltBit = false;    
    if (Msg.message == WM_SYSKEYDOWN || Msg.message == WM_SYSKEYUP)
        AltBit = (Msg.lParam & (1 << 29)) != 0;

    if ((Msg.message == WM_SYSKEYUP || Msg.message == WM_KEYUP) && !Extended && !AltBit && VirtualKeyCode == 18)
    {
        // Left Alt
        return KeyCodes::VK_LEFTALT;
    }

    // Left Ctrl
    if (!Extended && !AltBit && VirtualKeyCode == 17)
    {
        // Peek for the next message.
        MSG nextMsg;
        BOOL nextMessageFound = PeekMessage(&nextMsg, NULL, 0, 0, PM_NOREMOVE);

        // If the next message is for the right Alt:
        if (nextMessageFound && nextMsg.message == Msg.message && nextMsg.wParam == 18)
        {
            //
            bool nextExtended = (nextMsg.lParam & (1 << 24)) != 0;

            //
            bool nextAltBit = false;    
            if (nextMsg.message == WM_SYSKEYDOWN || nextMsg.message == WM_SYSKEYUP)
                nextAltBit = (nextMsg.lParam & (1 << 29)) != 0;

            // If it is really for the right Alt
            if (nextExtended && !nextAltBit)
            {
                // Remove the next message
                PeekMessage(&nextMsg, NULL, 0, 0, PM_REMOVE);

                // Right Alt
                return KeyCodes::VK_RIGHTALT;
            }
        }

        // Left Ctrl
        return KeyCodes::VK_LEFTCTRL;
    }

    if (Msg.message == WM_SYSKEYUP && !Extended && AltBit && VirtualKeyCode == 17)
    {
        // Peek for the next message.
        MSG nextMsg;
        BOOL nextMessageFound = PeekMessage(&nextMsg, NULL, 0, 0, PM_NOREMOVE);

        // If the next message is for the right Alt:
        if (nextMessageFound && nextMsg.message == WM_KEYUP && nextMsg.wParam == 18)
        {
            //
            bool nextExtended = (nextMsg.lParam & (1 << 24)) != 0;

            //
            bool nextAltBit = false;    
            if (nextMsg.message == WM_SYSKEYDOWN || nextMsg.message == WM_SYSKEYUP)
                nextAltBit = (nextMsg.lParam & (1 << 29)) != 0;

            // If it is really for the right Alt
            if (nextExtended && !nextAltBit)
            {
                // Remove the next message
                PeekMessage(&nextMsg, NULL, 0, 0, PM_REMOVE);

                // Right Alt
                return KeyCodes::VK_RIGHTALT;
            }
        }
    }

    // Right Ctrl
    if (Extended && !AltBit && VirtualKeyCode == 17)
        return KeyCodes::VK_RIGHTCTRL;

    // Left Alt
    if (!Extended && AltBit && VirtualKeyCode == 18)
        return KeyCodes::VK_LEFTALT;

    // Default
    return VirtualKeyCode;
}

1
কোডের জন্য +1, তবে যোদার মতো কথা বলার জন্য -1। এটি বিরক্তিকর এবং আপনার উত্তরগুলি পড়া শক্ত করে তোলে।
অ্যান্থনি

প্রকৃতপক্ষে, এটি রসিকতা অ্যাকাউন্টগুলির জন্য কোনও জায়গা নয়।
কোডরেঞ্জার

2

আপনি চেষ্টা করে দেখতে পারেন DirectInput এপিআই আরো সম্প্রতি, বা, xinput এপিআই


1
এক্সিম্পট কি কেবলমাত্র এক্সবক্স 360 কন্ট্রোলারের জন্য পিসির সাথে সংযুক্ত নেই? আমি ডাইরেক্টইনপুটটি কিছুটা অপ্রচলিত পড়েছি তাই আমি এটি ব্যবহার এড়াতে চেষ্টা করেছি। তবে আমি ডাইরেক্টইনপুটটিও চেষ্টা করেছি এবং ভালভাবে জেগেছি।
ডিলাক্স

এক্সআইএনপুট কেবলমাত্র গেমপ্যাডগুলির জন্য। উইন্ডোজ 10 হিসাবে, এক্সআইএনপুটকে 'আইগেমপ্যাড' ইন্টারফেসের পক্ষে অবহেলা করা হয়েছে। সর্বোপরি আপনার অন্যান্য ব্যবস্থাগুলির উপর থেকে RAW_INPUT ব্যবহার করা উচিত, যেহেতু তাদের মধ্যে সীমাবদ্ধতা রয়েছে।
লাভলপ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.