什么是在Windows Mobile的输入数字的最佳方式? (.NET CF 3.5)是在、方式、数字、Windows

2023-09-02 20:46:55 作者:背後的冷漠、

必须有一个比一个受限的数字上下按钮控制更好的办法。

There must be a better way than a constrained numeric updown control.

推荐答案

输入数字(特别是非整数),在Windows Mobile(或在一个普通的Windows应用程序)的最简单方法是只是有一个文本框的用户输入进去,然后确认,他们已经进入了一个合适的数字。

The easiest way to enter numbers (especially non-integer numbers) in Windows Mobile (or in a regular Windows application) is to just have a text box that the users type into, and then validate that they've entered a proper number.

在Windows Mobile的这种方法的问题是,默认的SIP(软输入面板又名小弹出键盘)看起来是这样的:

The problem with this approach in Windows Mobile is that the default SIP (Soft Input Panel aka little pop-up keyboard) looks like this:

在一个真正的Windows Mobile设备中,SIP看起来比这个更小,它是在凯斯特正确命中的小数字键在顶部一个巨大的痛苦。要使用这个目的是什么数字模式,它让你通过点击左上角的123按钮,如下所示:

On a real Windows Mobile device, the SIP looks even smaller than this, and it is a gigantic pain in the keister to hit the little number keys at the top correctly. What you want to use for this purpose is the Numeric mode, which you get by clicking the "123" button in the upper left corner, and looks like this:

的问题,这是不存在(简单)的方式编程以使所述SIP这种模式出现,而不是常规键盘。要获取SIP出现在数字模式,将引用添加到您的项目为 Microsoft.WindowsCE.Forms ,然后再增加code为一个名为SIPHandler类(你将不得不更改命名空间到你的项目的命名空间):

The problem with this is that there is no (simple) way programatically to make this mode of the SIP appear instead of the regular keyboard. To get the SIP to appear in numeric mode, add a reference to your project to Microsoft.WindowsCE.Forms, and then add this code as a class named "SIPHandler" (you will have to change the namespace to your project's namespace):

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using Microsoft.WindowsCE.Forms;

namespace DeviceApplication1
{
    /// <summary>
    /// Handles showing and hiding of Soft Input Panel (SIP).  Better to use these
    /// methods than having an InputControl on a form.  InputControls behave oddly
    /// if you have multiple forms open.
    /// </summary>
    public class SIPHandler
    {
        public static void ShowSIP()
        {
            SipShowIM(1);
        }

        public static void ShowSIPNumeric()
        {
            SipShowIM(1);
            SetKeyboardToNumeric();
        }

        public static void ShowSIPRegular()
        {
            SipShowIM(1);
            SetKeyboardToRegular();
        }

        public static void HideSIP()
        {
            SipShowIM(0);
        }

        private static void SetKeyboardToRegular()
        {
            // Find the SIP window
            IntPtr hWnd = FindWindow("SipWndClass", null);
            // Go one level below as the actual SIP window is a child
            hWnd = GetWindow(hWnd, GW_CHILD);
            // Obtain its context and get a color sample
            // The premise here is that the numeric mode is controlled by a virtual button in the top left corner
            // Whenever the numeric mode is active, the button background will be of COLOR_WINDOW_TEXT
            IntPtr hDC = GetDC(hWnd);
            int pixel = GetPixel(hDC, 2, 2);
            // Notice that we cannot simply compare the color to the system color as the system color is 24 bit (or palette)
            // and the real color is dithered to 15-16 bits for most devices, so white (0xff, 0xff, 0xff) becomes
            // almost white (oxf8, 0xfc, 0xf8)

            // ken's hack:  here we only want to simulate the click if the keyboard is in numeric mode, in 
            // which case the back color will be WindowText
            //int clrText = (SystemColors.Window.R) | (SystemColors.Window.G << 8) | (SystemColors.Window.B << 16);
            int clrText = (SystemColors.WindowText.R) | (SystemColors.WindowText.G << 8) | (SystemColors.WindowText.B << 16);

            SetPixel(hDC, 2, 2, clrText);
            int pixelNew = GetPixel(hDC, 2, 2);
            // Restore the original pixel
            SetPixel(hDC, 2, 2, pixel);

            if (pixel == pixelNew)
            {
                // Simulate stylus click
                Message msg = Message.Create(hWnd, WM_LBUTTONDOWN, new IntPtr(1), new IntPtr(0x00090009));
                MessageWindow.SendMessage(ref msg);
                msg = Message.Create(hWnd, WM_LBUTTONUP, new IntPtr(0), new IntPtr(0x00090009));
                MessageWindow.SendMessage(ref msg);
            }
            // Free resources
            ReleaseDC(hWnd, hDC);
        }

        private static void SetKeyboardToNumeric()
        {
            // Find the SIP window
            IntPtr hWnd = FindWindow("SipWndClass", null);
            // Go one level below as the actual SIP window is a child
            hWnd = GetWindow(hWnd, GW_CHILD);
            // Obtain its context and get a color sample
            // The premise here is that the numeric mode is controlled by a virtual button in the top left corner
            // Whenever the numeric mode is active, the button background will be of COLOR_WINDOW_TEXT
            IntPtr hDC = GetDC(hWnd);
            int pixel = GetPixel(hDC, 2, 2);
            // Notice that we cannot simply compare the color to the system color as the system color is 24 bit (or palette)
            // and the real color is dithered to 15-16 bits for most devices, so white (0xff, 0xff, 0xff) becomes
            // almost white (oxf8, 0xfc, 0xf8)
            int clrText = (SystemColors.Window.R) | (SystemColors.Window.G << 8) | (SystemColors.Window.B << 16);
            SetPixel(hDC, 2, 2, clrText);
            int pixelNew = GetPixel(hDC, 2, 2);
            // Restore the original pixel
            SetPixel(hDC, 2, 2, pixel);

            if (pixel == pixelNew)
            {
                // Simulate stylus click
                Message msg = Message.Create(hWnd, WM_LBUTTONDOWN, new IntPtr(1), new IntPtr(0x00090009));
                MessageWindow.SendMessage(ref msg);
                msg = Message.Create(hWnd, WM_LBUTTONUP, new IntPtr(0), new IntPtr(0x00090009));
                MessageWindow.SendMessage(ref msg);
            }
            // Free resources
            ReleaseDC(hWnd, hDC);
        }

        [DllImport("coredll.dll")]
        private extern static bool SipShowIM(int dwFlag);

        [DllImport("coredll.dll")]
        private extern static IntPtr FindWindow(string wndClass, string caption);

        [DllImport("coredll.dll")]
        private extern static IntPtr GetWindow(IntPtr hWnd, int nType);

        [DllImport("coredll.dll")]
        private extern static int GetPixel(IntPtr hdc, int nXPos, int nYPos);

        [DllImport("coredll.dll")]
        private extern static void SetPixel(IntPtr hdc, int nXPos, int nYPos, int clr);

        [DllImport("coredll.dll")]
        private extern static IntPtr GetDC(IntPtr hWnd);

        [DllImport("coredll.dll")]
        private extern static void ReleaseDC(IntPtr hWnd, IntPtr hDC);

        [DllImport("coredll.dll")]
        private static extern bool SipSetCurrentIM(byte[] clsid);

        const int WM_LBUTTONDOWN = 0x0201;
        const int WM_LBUTTONUP = 0x0202;
        const int GW_CHILD = 5;

    }
}

抱歉的长度。要弹出SIP在数字模式,你只需要使用这一行:

Sorry about the length. To pop the SIP up in numeric mode, you just use this line:

SIPHandler.ShowSIPNumeric();

或使之出现在常规的键盘模式:

or to make it appear in regular keyboard mode:

SIPHandler.ShowSIPRegular();

和再次隐藏它:

SIPHandler.HideSIP();

这背后code的基本关键是要排序在左上角的颜色的偷看来确定所述SIP是否已在常规键盘或数字模式,然后以模拟鼠标点击(如果有必要)在相同的角,以确保SIP是在所希望的模式。

The basic trick behind this code is to sort of "peek" the color in the upper left corner to determine whether the SIP is already in regular keyboard or numeric mode, and then to simulate a mouse click (if necessary) in the same corner to ensure that the SIP is in the mode desired.

注:这是借网络code,但我已经不知道我在哪里,从得到它。如果有人对SO知道哪里该黑客来自,请让我知道,我会很乐意将其归因于原作者。

Note: this is "borrowed" web code, but I no longer know where I got it from. If anyone on SO knows where this hack came from, please let me know and I'll be happy to attribute it to the original author.

更新:还有2秒的谷歌搜索后,我发现这个code近因来源是丹尼尔蛾:

Update: well, after 2 seconds of Googling, I've found that the proximate source of this code was Daniel Moth:

http://www.danielmoth.com/Blog/InputPanelEx.cs

...谁学分亚历费恩曼与原来的:

... who credits Alex Feinman with the original:

http://www.alexfeinman.com/download.asp?doc=IMSwitch.zip

谢谢你们!这code居然把我带到了眼泪一次(我砍洋葱的时候,但不可能是它)。

Thanks, guys! This code actually brought me to tears once (I was chopping onions at the time, but that couldn't have been it).