ラベル .NET(Mobile) の投稿を表示しています。 すべての投稿を表示
ラベル .NET(Mobile) の投稿を表示しています。 すべての投稿を表示

OeacleLite GroupBy句とOrderBy句は一緒に使えない

OracleLite10gで、GroupBy句とOrderBy句を一緒に使用するとソートされません。

以下のようなsqlはOrderBy句が無視されます。
SELECT hoge1, hoge2, hoge3
FROM table
GROUP BY hoge1, hoge2, hoge3
ORDER BY hoge3

この問題を回避するために、GroupBy句を副表にします。
SELECT hoge1, hoge2, hoge3
FROM (SELECT hoge1, hoge2, hoge3 FROM table GROUP BY hoge1, hoge2, hoge3)
ORDER BY hoge3

.Net(Mobile) 無線Lan(WiFi)のON/OFFを行うには

無線LanのON/OFFを行うにはSetDevicePowerというAPIを使用します。
このSetDevicePowerの第一引数に渡す値が端末により異なるので注意が必要です。

手元にある機種がSoftbankのX04HTとDocomoのX01Aだけなので、この2台で確認した結果です。

まず端末のレジストリ「HEKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Power/State」を確認します。
{98C5250D-C29A-4985-AE5F-AFE5367E5006}で始まるものが無線Lanになります。この値が1なら接続状態で0が切断状態です。

{98C5250D-C29A-4985-AE5F-AFE5367E5006}の後に続く¥以降の文字列が端末により異なります。
SoftbankのX04HTは{98C5250D-C29A-4985-AE5F-AFE5367E5006}¥TNETW12511
DocomoのX01Aは{98C5250D-C29A-4985-AE5F-AFE5367E5006}¥AR6K_SD1

この¥以降の文字列はレジストリ「HEKEY_LOCAL_MACHINE/Software/Drivers/WLAN」の「AdapterName」の値です。


以下のサンプルコードはSoftbankのX04HTとDocomoのX01Aで検証しましたが、他の端末で動作するかわかりません。
Imports System.Runtime.InteropServices

Public Class Form1

    Private Enum DevicePowerState
        Unspecified = -1
        D0 = 0 ' Full On: full power, full functionality  
        D1 ' Low Power On: fully functional at low power/performance  
        D2 'Standby: partially powered with automatic wake  
        D3 'Sleep: partially powered with device initiated wake  
        D4 'Off: unpowered  
    End Enum

     _
    Private Shared Function SetDevicePower(ByVal pvDevice As String, ByVal dwDeviceFlags As Int32, ByVal deviceState As DevicePowerState) As Int32
    End Function

     _
    Private Shared Function DevicePowerNotify(ByVal pvDevice As String, ByVal state As DevicePowerState, ByVal dwDeviceFlags As Int32) As Int32
    End Function

    Private Const POWER_NAME As Int32 = 1

    Private Const wifiGUID As String = "{98C5250D-C29A-4985-AE5F-AFE5367E5006}"


    'WirelessLan ON
    Private Sub Button10_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button10.Click
        SetWiFi(True)
    End Sub

    'WirelessLan OFF
    Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click
        SetWiFi(False)
    End Sub

    Private Sub SetWiFi(ByVal isEnabled As Boolean)
        'レジストリよりWiFiのドライバ名を取得する
        Dim regDrivers As RegistryKey = Registry.LocalMachine.CreateSubKey("Software\Drivers\WLAN")
        Dim driverNm As String = regDrivers.GetValue("AdapterName").ToString
        Dim guid As String = wifiGUID & "¥" & driverNm


        'D0でON、D4でOFF
        If (isEnabled) Then
            DevicePowerNotify(guid, DevicePowerState.D0, POWER_NAME)
            SetDevicePower(guid, POWER_NAME, DevicePowerState.D0)
        Else
            DevicePowerNotify(guid, DevicePowerState.D4, POWER_NAME)
            SetDevicePower(guid, POWER_NAME, DevicePowerState.D4)
        End If
    End Sub
End Class

.Net(Mobile) BlutoothのON/OFFを行うには

BlutoothのON/OFFを行うにはBthSetModeというAPIを使用します。

Imports System.Runtime.InteropServices

Public Class Form1
    Public Enum RadioMode
        RadioOff = 0            'Bluetooth OFF
        Connectable = 1         'Bluetooth ON(他のデバイスから検索不可)
        Discoverable = 2        'Bluetooth ON(他のデバイスから検索可)
    End Enum
    
     _
    Public Shared Function BthGetMode(ByRef dwMode As RadioMode) As Integer
    End Function
    
     _
    Public Shared Function BthSetMode(ByVal dwMode As RadioMode) As Integer
    End Function

    'Bluetooth ON
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        SetBluetooth(True)
    End Sub
    
    'Bluetooth OFF
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        SetBluetooth(False)
    End Sub

    Private Sub SetBluetooth(ByVal isEnabled As Boolean)
        If (isEnabled) Then
            Dim mode As RadioMode = RadioMode.RadioOff
            Dim ret As Integer = BthGetMode(mode)
            If mode = RadioMode.RadioOff Then
                ret = BthSetMode(RadioMode.Discoverable)
                If ret = 0 Then
                    Do
                        System.Threading.Thread.Sleep(100)
                        ret = BthGetMode(mode)
                        If ret <> 0 OrElse mode <> RadioMode.RadioOff Then
                            Exit Do
                        End If
                    Loop
                End If
            End If
        Else
            Dim mode As RadioMode = RadioMode.Connectable
            Dim ret As Integer = BthGetMode(mode)
            If mode = RadioMode.Connectable Or mode = RadioMode.Discoverable Then
                ret = BthSetMode(RadioMode.RadioOff)
            End If
        End If
    End Sub
End Class

.Net(Mobile) NumericUpDownコントロールで値を選択状態にする。

CompactFrameworkではNumericUpDownコントロールのSelectAllプロパティがありません。
NumericUpDownコントロールで値を選択状態にするにはAPIを使用します。

Public Class FrmPrint

    Public Const SETSEL As Integer = &HB1
    <DllImport("coredll")> _
    Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    End Function

    'NumericUpDownコントロールにFocusされた時、値を選択状態にする。
    Private Sub NumericUpDown1_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) _
    HandlesNumericUpDown1.GotFocus
            '入力文字を全選択する
            Dim nud As NumericUpDown = DirectCast(sender, NumericUpDown)
            SendMessage(nud.Handle, SETSEL, 0, nud.Value.ToString.Length)
    End Sub
    
End Class

.NET(Mobile) 回避できなかった問題

リンクコントロールを継承したカスタムコントロールを作成し、デザイナでフォームに配置すると描画が正しく行われない。

リンクコントロールでTabStopプロパティをデザイナでFalseに設定しても、ビルドするとTrueに戻ってしまう。

リンクコントロールのTabStopプロパティをコードでFalseに設定しても、下矢印キーでFocus移動させるとFocus出来てしまう。

TextBoxのValidatingイベントやLostFocusイベントでTextBoxにFocusさせると、SIPから数字以外の入力を受け付けなくなる。(X04HT限定?)

.NET(Mobile) フォームのActiveControlを探す

CompactFrameworkでフォームのActiveControlを探す方法です。
ComapactFrameworkではFormクラスのActiveControlプロパティがサポートされていません。


Public Class MyForm
    Inherits System.Windows.Forms.Form

    Public Overridable Property ActiveControl() As Control
        Get
            Return GetFocusedControl(Me)
        End Get
        Set(ByVal Value As Control)
             If (Not (Value.Focused)) Then
                Value.Focus()
             End If
        End Set
    End Property


    Private Function GetFocusedControl(ByRef parent As Control) As Control
        If (parent.Focused) Then
            Return parent
        End If

         For Each ctrl As Control In parent.Controls
             Dim temp As Control = GetFocusedControl(ctrl)
             If (Not (temp Is Nothing)) Then
                 Return temp
             End If
         Next

        Return Nothing
    End Function
End Class

.NET(Mobile) コントロールの移動

CompactFrameworkでコントロール間をEnterキーと上下矢印キーで移動する方法です。

まず通常のコントロールでEnterキーと上下矢印キーのデフォルト操作をまとめました。
使用した機種はX04HTです。機種によりデフォルト操作が異なります。
コントロールEnterキー上下矢印キー
TextBox動作なし動作なし
ComboBoxドロップダウンリストの展開リストアイテムの選択
DateTimePickerカレンダーの表示値のインクリメント
NumericUpDown動作なし値のインクリメント
CheckBoxチェックON/OFFコントロールの移動
RadioButton動作なしコントロールの移動
LinkLabelClickイベント発生コントロールの移動
ButtonClickイベント発生コントロールの移動

TextBoxではMultiLineプロパティがFalseであればコントロールを移動するようにします。
Enterキーではモバイル開発 TextBoxのTextAlignプロパティの対策を入れる必要もあります。

ComboBox、DateTimePickerではEnterキーのデフォルト操作「ドロップダウンリストの展開」は残し、上下矢印キーはドロップダウンリストが展開していない場合はコントロールを移動とすると操作性が良いと思います。
ドロップダウンが展開しているかどうかはモバイル開発 Controlのドロップダウンが展開されているかを取得するを見てください。

NumericUpDownはどうしますか・・・

コントロールをEnterキーで移動するサンプル
Private Sub KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
    Select Case e.KeyChar
     Case Chr(Keys.Enter)
        Call Api.keybd_event(Api.VK_TAB, 0, 0, 0)
        Call Api.keybd_event(Api.VK_TAB, 0, Api.KEYEVENTF_KEYUP, 0)
        e.Handled = True
    End Select
End Sub


コントロールを上下矢印キーで移動するサンプル
Private Sub KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs)
    Select Case e.KeyCode
     Case Keys.Up
         Call Api.keybd_event(Api.VK_SHIFT, 0, 0, 0)
         Call Api.keybd_event(Api.VK_TAB, 0, 0, 0)
         Call Api.keybd_event(Api.VK_TAB, 0, Api.KEYEVENTF_KEYUP, 0)
         Call Api.keybd_event(Api.VK_SHIFT, 0, Api.KEYEVENTF_KEYUP, 0)
         e.Handled = True

     Case Keys.Down
        Call Api.keybd_event(Api.VK_TAB, 0, 0, 0)
        Call Api.keybd_event(Api.VK_TAB, 0, Api.KEYEVENTF_KEYUP, 0)
        e.Handled = True
    End Select
End Sub


API
Public Class Api
    Public Const VK_SHIFT As Integer = &H10
    Public Const VK_TAB As Integer = &H9
    Public Const KEYEVENTF_KEYUP As Integer = &H2

     _
    Public Shared Function keybd_event(ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer) As Integer
    End Function
End Class

.NET(Mobile) Controlのドロップダウンが展開されているかを取得する

CompactFrameworkでComboBoxやDateTimePickerのドロップダウンリストが展開されているかどうかを取得するサンプルです。
CompactFrameworkではDroppedDownプロパティがサポートされていないのでAPIを使用します。

Dim isDroppedDown As boolean
Dim cbo As ComboBox = Me.ComboBox1
If Api.SendMessage(cbo.Handle, Api.GETDROPPEDSTATE, 0, 0) = 1 Then
    isDroppedDown = True
Else
    isDroppedDown = False
End If


API
Public Class Api
    Public Const GETDROPPEDSTATE As Integer = &H157
     _
    Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    End Function
End Class

.NET(Mobile) メモリ使用量を表示する

ComactFrameworkでモバイルのメモリ使用量を表示するサンプルです。

Public Class Memory
    Public Structure MEMORYSTATUS
         Public dwLength As Integer
         Public dwMemoryLoad As Integer
         Public dwTotalPhys As Integer         '合計 物理メモリ
         Public dwAvailPhys As Integer         '空き 物理メモリ
         Public dwTotalPageFile As Integer
         Public dwAvailPageFile As Integer
         Public dwTotalVirtual As Integer      '合計 仮想メモリ
         Public dwAvailVirtual As Integer      '空き 仮想メモリ
    End Structure

     _
    Public Shared Function GlobalMemoryStatus(ByRef ms As MEMORYSTATUS) As Integer
    End Function

     _
    Public Shared Function GetSystemMemoryDivision(ByRef lpdwStorePages As Integer, ByRef ldpwRamPages As Integer, ByRef ldpwPageSize As Integer) As Integer
    End Function


    Public Shared Sub ShowMemory()
        Dim storePages As Integer
        Dim ramPages As Integer
        Dim pageSize As Integer
        Dim res As Integer = GetSystemMemoryDivision(storePages, ramPages, pageSize)

        Dim memStatus As New MEMORYSTATUS
        GlobalMemoryStatus(memStatus)

        Dim MemoryInfo As New System.Text.StringBuilder
        MemoryInfo.AppendLine("合計物理メモリ: " & memStatus.dwTotalPhys.ToString("#,##0"))
        MemoryInfo.AppendLine("使用物理メモリ: " & (memStatus.dwTotalPhys - memStatus.dwAvailPhys).ToString("#,##0"))
        MemoryInfo.AppendLine("空き物理メモリ: " & memStatus.dwAvailPhys.ToString("#,##0"))
        MemoryInfo.AppendLine("使用率:" & CInt(((memStatus.dwTotalPhys - memStatus.dwAvailPhys) / memStatus.dwTotalPhys) * 100) & "%")
        MemoryInfo.AppendLine()
        MemoryInfo.AppendLine("合計仮想メモリ: " & memStatus.dwTotalVirtual.ToString("#,##0"))
        MemoryInfo.AppendLine("使用仮想メモリ: " & (memStatus.dwTotalVirtual - memStatus.dwAvailVirtual).ToString("#,##0"))
        MemoryInfo.AppendLine("空き仮想メモリ: " & memStatus.dwAvailVirtual.ToString("#,##0"))
        MemoryInfo.AppendLine("使用率:" & CInt(((memStatus.dwTotalVirtual - memStatus.dwAvailVirtual) / memStatus.dwTotalVirtual) * 100) & "%")
        MemoryInfo.AppendLine()
        MemoryInfo.AppendLine("GC.GetTotalMemory:" & GC.GetTotalMemory(False).ToString("#,##0"))
        System.Windows.Forms.MessageBox.Show(MemoryInfo.ToString())
    End Sub
End Class



Memory.ShowMemory()

.NET(Mobile) TextBoxのTextAlignプロパティ

CompactFramework標準のTextBoxではTextAlignプロパティの選択肢はLEFTしかありません。
これはTextBoxのMultiLineをTrueにすることでTextALignプロパティの選択肢がLEFT、RIGHT、CENTERになります。
もちろんEnterキー押下時に改行しないようにしなければなりません。

.NET(Mobile) おすすめコントロール集

久しぶりの更新です。
モバイルの開発がちょっと忙しかったので、JAVAの試験勉強とブログの更新をサボっていました(いいわけ)。
年内の仕事はあるけれど(・・・年明けの仕事はない・・・・)かな~り暇なので、ブログ更新と試験勉強の再開です。


まずはモバイル開発(CompactFramework)のメモから

モバイル開発で最初につまづくのはコントロールのショボサです。
こういうことしたいのに、コントロールがない!
自分で作るには時間もないし面倒・・・


そんなときはコレがお勧めです!!
Resco MobileForms Toolkit

お値段はStandard Editionで$599.95。
今は円高なので購入のチャンスです。


今回はこのコントロール集のSmartGridコントロール、AdvanceListコントロール、ImageButtonコントロールを使用しました。

SmartGridは入力可能で、行選択モードなどもあり、画像も表示出来ます。
標準での入力はテキストボックス、チェックボックスですが、カスタムでWindowsFormsControlが使用できます。
自由自在にカスタマイズできるとは言い難いですが、標準のグリッドに比べれば大変優秀です。
タッチスクロールが可能で、スクロール方向、スクロールスピードを調整できます。



AdvanceListコントロールは展開可能なアコーディオンコントロールみたいな感じです。
モバイルの画面は小さいので一覧画面で使用すると効果的です。
選択していないときは最小限の情報だけを表示し、行を選択すると展開し詳細な情報を表示できます。
標準でリンクコントロールやボタンコントロール、画像を配置できますが、基本的に表示のみのコントロールです。
入力可能のセルを配置することも一応は可能です。
タッチスクロールが可能で、スクロール方向、スクロールスピードを調整できます。



ImageButtonコントロールは画像を配置できるコントロールです。
画像ボタンだけでなく、通常のボタン、リンクコントロールの代用もできます。
画像と文字の配置を調整できるのがうれしいです。




まったく問題がないかといえばウソになりますが、WindowsFormsControlに比べれば
非常に優秀ですっ!!


問題はサポートが英語なこと。
そして購入すると英語で電話がかかってきます。ヽ(д`ヽ)。。オロオロ。。(ノ´д)ノ

.NET(Mobile) SIPパネルを切り替えるには

Touch Diamond (X04HT)のSIPはデフォルトで以下の5種類があります。
・10キー
・ひらがな/カタカナ
・ローマ字/かな
・手書き入力
・手書き検索

このSIPパネルを切り替えます。
方法は2つあります。

Microsoft.WindowsCE.Forms.InputMethodクラスを使用する方法です。
フォームにInputPanelを配置し、以下のコードを実行する。
Public Class Form1

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim im As Microsoft.WindowsCE.Forms.InputMethod
For Each im In Me.InputPanel1.InputMethods
Me.ListBox1.Items.Add(im.Name)
Next im

End Sub

Private Sub ListBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim strIM As String
strIM = ListBox1.SelectedItem.ToString()

Dim im As Microsoft.WindowsCE.Forms.InputMethod
For Each im In Me.InputPanel1.InputMethods
If im.Name = strIM Then
InputPanel1.CurrentInputMethod = im
End If
Next im
End Sub

End Class


こちらはAPI「SipSetCurrentIM」を使用します。
フォームにInputPanelを配置する必要はありません。
Imports System.Runtime.InteropServices

Public Class Form1

Private _InputMethod As New Dictionary(Of String, Guid)

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each im As Microsoft.WindowsCE.Forms.InputMethod In Me.InputPanel1.InputMethods
_InputMethod.Add(im.Name, im.Clsid)
Me.ListBox1.Items.Add(im.Name)
Next im
End Sub

Private Sub ListBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim strIM As String = ListBox1.SelectedItem.ToString()
Dim guid As Guid = Me._InputMethod(strIM)

SipSetCurrentIM(guid.ToByteArray)
End Sub

 _
Private Shared Function SipSetCurrentIM(ByVal clsid As Byte()) As Boolean
End Function

End Class

.NET(Mobile) Touch Diamond (X04HT)のデフォルト10キーSIPの入力モードを切り替える

Touch Diamond (X04HT)のデフォルト10キーSIPの入力モードを切り替えるには
レジストリ「HKEY_CURRENT_USER\Software\Keytouch\Multiplay」の値を操作します。

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
SetKey10InputMode(CType(Me.ComboBox1.SelectedIndex, Key10ModeType))
End Sub

Public Enum Key10ModeType
NumHalf = 0
NumFull = 1
AlphaHalf = 2
AlphaFull = 3
Hiragana = 4
KatakanaHalf = 5
KatakanaFull = 6
End Enum

Private Sub SetKey10InputMode(ByVal mode As Key10ModeType)
Dim sReg As String = "HKEY_CURRENT_USER\Software\Keytouch\Multiplay"

Select Case mode
Case Key10ModeType.NumHalf
Microsoft.Win32.Registry.SetValue(sReg, "ShiftModeEx", 9)
Microsoft.Win32.Registry.SetValue(sReg, "ShiftMode", 8)
Microsoft.Win32.Registry.SetValue(sReg, "ActiveIME", 1)
Microsoft.Win32.Registry.SetValue(sReg, "NumericMode", 0)
Microsoft.Win32.Registry.SetValue(sReg, "PasswordMode", 0)

Case Key10ModeType.NumFull
Microsoft.Win32.Registry.SetValue(sReg, "ShiftModeEx", 8)
Microsoft.Win32.Registry.SetValue(sReg, "ShiftMode", 7)
Microsoft.Win32.Registry.SetValue(sReg, "ActiveIME", 1)
Microsoft.Win32.Registry.SetValue(sReg, "NumericMode", 0)
Microsoft.Win32.Registry.SetValue(sReg, "PasswordMode", 0)

Case Key10ModeType.AlphaHalf
Microsoft.Win32.Registry.SetValue(sReg, "ShiftModeEx", 7)
Microsoft.Win32.Registry.SetValue(sReg, "ShiftMode", 6)
Microsoft.Win32.Registry.SetValue(sReg, "ActiveIME", 1)
Microsoft.Win32.Registry.SetValue(sReg, "NumericMode", 0)
Microsoft.Win32.Registry.SetValue(sReg, "PasswordMode", 0)


Case Key10ModeType.AlphaFull
Microsoft.Win32.Registry.SetValue(sReg, "ShiftModeEx", 6)
Microsoft.Win32.Registry.SetValue(sReg, "ShiftMode", 5)
Microsoft.Win32.Registry.SetValue(sReg, "ActiveIME", 1)
Microsoft.Win32.Registry.SetValue(sReg, "NumericMode", 0)
Microsoft.Win32.Registry.SetValue(sReg, "PasswordMode", 0)

Case Key10ModeType.Hiragana
Microsoft.Win32.Registry.SetValue(sReg, "ShiftModeEx", 0)
Microsoft.Win32.Registry.SetValue(sReg, "ShiftMode", 0)
Microsoft.Win32.Registry.SetValue(sReg, "ActiveIME", 202)
Microsoft.Win32.Registry.SetValue(sReg, "NumericMode", 0)
Microsoft.Win32.Registry.SetValue(sReg, "PasswordMode", 0)

Case Key10ModeType.KatakanaHalf
Microsoft.Win32.Registry.SetValue(sReg, "ShiftModeEx", 3)
Microsoft.Win32.Registry.SetValue(sReg, "ShiftMode", 2)
Microsoft.Win32.Registry.SetValue(sReg, "ActiveIME", 202)
Microsoft.Win32.Registry.SetValue(sReg, "NumericMode", 0)
Microsoft.Win32.Registry.SetValue(sReg, "PasswordMode", 0)

Case Key10ModeType.KatakanaFull
Microsoft.Win32.Registry.SetValue(sReg, "ShiftModeEx", 2)
Microsoft.Win32.Registry.SetValue(sReg, "ShiftMode", 1)
Microsoft.Win32.Registry.SetValue(sReg, "ActiveIME", 202)
Microsoft.Win32.Registry.SetValue(sReg, "NumericMode", 0)
Microsoft.Win32.Registry.SetValue(sReg, "PasswordMode", 0)

End Select
End Sub



ちなみに

W-ZERO3[es]本体表面の10キーを制御するのは
レジストリ「HKEY_CURRENT_USER\Software\Sharp\PhoneStatus」を操作します。

DT5200は本体表面の10キーを制御するのは
カシオのAPI「Calib.SystemLibNet.Api.SysSetInputMode」を使用します。
CASIOシステムライブラリマニュアル

モバイルのレジストリはVisualStudioの付属ツール「リモートレジストリエディタ」で見ることができます。

.NET(Mobile) コントロールのIMEモードを設定する

WindowsアプリであればテキストボックスのImeModeプロパティがありますが
CompactFrameworkのテキストボックスにはImeModeプロパティがありません。

CompactFrameworkのテキストボックスのImeModeを設定するにはAPIを使用します。
Imports System.Runtime.InteropServices

Public Class Form1

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Call SetImeMode(Me.TextBox1, ImeMode.HIRAGANA)
End Sub

Public Enum ImeMode
NOCONTROL = 0
OFF = 1
[ON] = 2
DISABLE = 3
HIRAGANA = 4
KATAKANA = 5
KATAKANAHALF = 6
ALPHAFULL = 7
ALPHA = 8
End Enum

Private Const ALPHANUMERIC As Int32 = &H0   '半角英数
Private Const NATIVE As Int32 = &H1         '直接入力
Private Const KATAKANA As Int32 = &H2       'カタカナ
Private Const FULLSHAPE As Int32 = &H8      '全角
Private Const ROMAN As Int32 = &H10

 _
Private Shared Function ImmGetContext(ByVal hWnd As IntPtr) As IntPtr
End Function

 _
Private Shared Function ImmReleaseContext(ByVal hWnd As IntPtr) As Boolean
End Function

 _
Private Shared Function ImmSetConversionStatus(ByVal hIMC As IntPtr, ByVal fdwConversion As Int32, ByVal fdwSentence As Int32) As Boolean
End Function

 _
Private Shared Function ImmSetOpenStatus(ByVal hIMC As IntPtr, ByVal fOpen As Int32) As Boolean
End Function

 _
Private Shared Function ImmAssociateContext(ByVal hWnd As IntPtr, ByVal hIMC As Int32) As Int32
End Function


Private Sub SetImeMode(ByVal ctrl As Control, ByVal mode As ImeMode)
Dim himc As IntPtr = ImmGetContext(ctrl.Handle)

Try
Select Case mode
Case ImeMode.DISABLE
ImmAssociateContext(himc, 0)

Case ImeMode.OFF
ImmAssociateContext(himc, 1)
ImmSetOpenStatus(himc, 0)

Case ImeMode.ON
ImmAssociateContext(himc, 1)
ImmSetOpenStatus(himc, 1)

Case Else

ImmAssociateContext(himc, 1)
ImmSetOpenStatus(himc, 1)

Dim dwConversion As Int32

Select Case mode
Case ImeMode.HIRAGANA
dwConversion = NATIVE Or FULLSHAPE Or ROMAN
Case ImeMode.KATAKANA
dwConversion = NATIVE Or FULLSHAPE Or KATAKANA Or ROMAN
Case ImeMode.KATAKANAHALF
dwConversion = NATIVE Or KATAKANA Or ROMAN
Case ImeMode.ALPHAFULL
dwConversion = FULLSHAPE Or ALPHANUMERIC
Case ImeMode.ALPHA
dwConversion = ALPHANUMERIC
End Select
ImmSetConversionStatus(himc, dwConversion, 0)



End Select
Finally
ImmReleaseContext(ctrl.Handle)
End Try

End Sub


End Class

.NET(Mobile) アプリのメモリ使用量について

CompactFrameworkアプリでフォームを開いたり閉じたりしていると、メモリ使用量がどんどん増えていきます。

Microsofrフィードバックによると
Inherits Componentしているコントロール(Timer、ToolTipなど)を使用する際に.Netが自動生成するコードが
CompactFrameworkでは自動生成されないためフォームの参照が解放されず、ガーベッジに収集されないらしいのです。

具体的にはCompactFrameworkのMainMenuコントロールはInherits Componentされているにもかかわらず、Desiner.vbでcomponentsに追加されずfinalizaで解放されないということです。
このコードの★部分が本来ならmainMenu1 = New System.Windows.Forms.Mainmenu(components)となる。
 _
Partial Public Class Form1
Inherits System.Windows.Forms.Form

'フォームがコンポーネントの一覧をクリーンアップするために dispose をオーバーライドします。
 _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub

'Windows フォーム デザイナで必要です。
Private components As System.ComponentModel.IContainer
Private mainMenu1 As System.Windows.Forms.MainMenu

'メモ: 以下のプロシージャは Windows フォーム デザイナで必要です。
'Windows フォーム デザイナを使用して変更できます。  
'コード エディタを使って変更しないでください。
 _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container
'★本来ならmainMenu1 = New System.Windows.Forms.Mainmenu(components)
mainMenu1 = New System.Windows.Forms.Mainmenu()
Me.Menu = mainMenu1
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi
Me.Text = "Form1"
Me.AutoScroll = True
End Sub
End Class



しかし、それでもメモリは増え続けていきます・・・・


ダイアログフォームを起動し、ダイアログフォームを閉じる処理を1000回行い100回ごとにメモリ使用量を計測する処理を
以下の7種類のコードで試してみました。

コード1
Form2を起動し、Form2のActivatedでForm2を閉じます。
Form2にはmainMenuコントロールを1つ配置しています。
Using句を使用します。
Me.ListBox1.Items.Add("開始" & " : " & GC.GetTotalMemory(False))
For i As Int32 = 1 To 1000
Using frm As New Form2
frm.ShowDialog()
End Using
If i Mod 100 = 0 Then
Me.ListBox1.Items.Add(i.ToString & " : " & GC.GetTotalMemory(False))
End If
Next


コード2
Form2を起動し、Form2のActivatedでForm2を閉じます。
Form2にはmainMenuコントロールを1つ配置しています。
Using句を使用します。
GC.Collectを1回実行します。
Me.ListBox1.Items.Add("開始" & " : " & GC.GetTotalMemory(False))
For i As Int32 = 1 To 1000
Using frm As New Form2
frm.ShowDialog()
End Using
GC.Collect()
If i Mod 100 = 0 Then
Me.ListBox1.Items.Add(i.ToString & " : " & GC.GetTotalMemory(False))
End If
Next


コード3
Form3を起動し、Form3のActivatedでForm3を閉じます。
Form3にはmainMenuコントロールを1つ配置しています。
Form3のmainMenuコントロールはmainMenu1 = New System.Windows.Forms.Mainmenu(components)とします。
Using句を使用します。
GC.Collectを1回実行します。
Me.ListBox1.Items.Add("開始" & " : " & GC.GetTotalMemory(False))
For i As Int32 = 1 To 1000
Using frm As New Form3
frm.ShowDialog()
End Using
GC.Collect()
If i Mod 100 = 0 Then
Me.ListBox1.Items.Add(i.ToString & " : " & GC.GetTotalMemory(False))
End If
Next


コード4
Form2を起動し、Form2のActivatedでForm2を閉じます。
Form2にはmainMenuコントロールを1つ配置しています。
Try~finally句を使用します。
Me.ListBox1.Items.Add("開始" & " : " & GC.GetTotalMemory(False))
For i As Int32 = 1 To 1000
Dim frm As New Form2
Try
frm.ShowDialog()
Finally
frm.Dispose()
End Try
If i Mod 100 = 0 Then
Me.ListBox1.Items.Add(i.ToString & " : " & GC.GetTotalMemory(False))
End If
Next


コード5
Form2を起動し、Form2のActivatedでForm2を閉じます。
Form2にはmainMenuコントロールを1つ配置しています。
Try~finally句を使用します。
GC.Collectを1回実行します。
Me.ListBox1.Items.Add("開始" & " : " & GC.GetTotalMemory(False))
For i As Int32 = 1 To 1000
Dim frm As New Form2
Try
frm.ShowDialog()
Finally
frm.Dispose()
End Try
GC.Collect()
If i Mod 100 = 0 Then
Me.ListBox1.Items.Add(i.ToString & " : " & GC.GetTotalMemory(False))
End If
Next


コード6
Form2を起動し、Form2のActivatedでForm2を閉じます。
Form2にはmainMenuコントロールを1つ配置しています。
Try~finally句を使用します。
Form2にNothingを設定します。
GC.Collectを1回実行します。
Me.ListBox1.Items.Add("開始" & " : " & GC.GetTotalMemory(False))
For i As Int32 = 1 To 1000
Dim frm As New Form2
Try
frm.ShowDialog()
Finally
frm.Dispose()
frm = Nothing
End Try
GC.Collect()
If i Mod 100 = 0 Then
Me.ListBox1.Items.Add(i.ToString & " : " & GC.GetTotalMemory(False))
End If
Next


コード7
Form3を起動し、Form3のActivatedでForm3を閉じます。
Form3にはmainMenuコントロールを1つ配置しています。
Form3のmainMenuコントロールはmainMenu1 = New System.Windows.Forms.Mainmenu(components)とします。
Try~finally句を使用します。
GC.Collectを1回実行します。
Me.ListBox1.Items.Add("開始" & " : " & GC.GetTotalMemory(False))
For i As Int32 = 1 To 1000
Dim frm As New Form3
Try
frm.ShowDialog()
Finally
frm.Dispose()
End Try
GC.Collect()
If i Mod 100 = 0 Then
Me.ListBox1.Items.Add(i.ToString & " : " & GC.GetTotalMemory(False))
End If
Next




コード1、コード4はメモリ使用量はほぼ同じですが、他のコードと比べGC.Collectを実行していないので、最もメモリ使用量が高いです。
コード6以外のその他のコードはメモリ使用量はほぼ同じです。
圧倒的にメモリ使用量が少なく、メモリ増加量も少ないのがコード6でした。

う~ん・・・?ナゼ?

.NET(Mobile) SIPの情報(表示状態、高さ、作業領域)を取得するには?

SIPの情報(表示状態、高さ、作業領域)するには SipGetInfo APIを使用します。
<DllImport("coredll.dll")> _
Public Structure SIPINFO
Public cbSize As Int32
Public fdwFlags As Int32
Public rcVisibleDesktop As RECT
Public rcSipRect As RECT
Public dwImDataSize As Int32
Public pvImData As IntPtr
End Structure

Public Structure RECT
Public left As Int32
Public top As Int32
Public right As Int32
Public bottom As Int32
End Structure

Private Const SIPF_DOCKED As Integer = 0
Private Const SIPF_LOCKED As Integer = 1
Private Const SIPF_OFF As Integer = 2
Private Const SIPF_ON As Integer = 3

<DllImport("coredll.dll")> _
Private Shared Function SipGetInfo(ByRef pSipInfo As SIPINFO) As Boolean
End Function


Private Sub cmdShipInfo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles cmdShipInfo.Click

Dim info As SIPINFO
info.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(info)
Call SipGetInfo(info)

'SIP起動状態
Dim isSipOpen As Boolean 
If info.fdwFlags = SIPF_ON Then
isSipOpen = True
ElseIf info.fdwFlags = SIPF_OFF Then
isSipOpen = False
End If
'SIPの高さ
Dim iSipHeight As Integer = info.rcSipRect.bottom - info.rcSipRect.top
'作業領域
Dim iDesktopHeight As Integer = info.rcVisibleDesktop.bottom - info.rcVisibleDesktop.top

MessageBox.Show(String.Format("Sip起動:{0} Sipの高さ:{1} 作業領域の高さ:{2}", isSipOpen, iSipHeight, iDesktopHeight))

End Sub


WS007SH(Willcom)では以下の値が返りました。
SIPが表示されていない状態
Sip起動:False Sipの高さ:160 作業領域の高さ:376
SIPが表示されている状態
Sip起動:True Sipの高さ:160 作業領域の高さ:588


X04HT(SoftBank)では以下の値が返りました。
SIPが表示されていない状態
Sip起動:False Sipの高さ:318 作業領域の高さ:218
SIPが表示されている状態
Sip起動:True Sipの高さ:318 作業領域の高さ:588


DT-5200(CASIO)ではSIPINFO.fdwFlags がSIPF_DOCKED(表示)/SIPF_LOCKED(非表示)になるようです。
DT-5200ではプログラムを以下のように修正します。
'SIP起動状態
Dim isSipOpen As Boolean 
If info.fdwFlags = SIPF_LOCKED Then
isSipOpen = True
ElseIf info.fdwFlags = SIPF_DOCKED Then
isSipOpen = False
End If

SIPが表示されていない状態
Sip起動:False Sipの高さ:105 作業領域の高さ:294
SIPが表示されている状態
Sip起動:True Sipの高さ:105 作業領域の高さ:294
※作業領域の高さがSIPが起動している時も起動していない時も変わらない。

DT-5200はSIPがタスクバーにあるけれど
X04HT、WS007SHはFormのMainMenuでSIPが起動するからその違いなのかな・・・

.NET(Mobile) SIPを表示するには?

SIP(Software Input Panel)を表示するには SipShowIM APIを使用します。
<DllImport("coredll.dll")> _
Private Shared Function SipShowIM(ByVal fOpen As Int32) As Boolean
End Function

'SIPを表示します。
Private Sub ShpShow_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles cmdSipShow.Click
Call SipShow(True)
End Sub

'SIPを閉じます。
Private Sub ShpCloas_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles cmdSipClose.Click
Call SipShow(False)
End Sub

.NET(Mobile) 高DPI対応

VGAとは640×480(192dpi)、QVGAとは320×240(96dpi)です。
WS007SH、X04HTはVGA。
CASIO DT-5200はQVGAとVGAが切り替え可能ですが、QVGAは320×240(96dpi)、VGAは640×480(96dpi)になります。
※640×480(96dpi)のVGAをRealVGAと呼ぶそうです。
RealVGAは情報量は多いですが文字も非常に小さいです。

同じアプリをQVGA機種で動かすと正常に表示されるが、VGA機種で動かすと表示が崩れることがあります。
表示が崩れる現象を確認するために簡単なプログラムを実行してみます。

フォームにパネルを1つ配置し、サイズプロパティをWidth=100、Height=100 にします。
そしてボタンを配置し、クリックイベントに以下のコードを書いて実行してみました。
Me.Panel1.Size = New Size(100, 100)
Size(100,100)のパネルを、ボタンクリックでもう一度Size(100,100)を設定しているだけですが
ボタンクリック後はパネルの幅、高さが半分になってしまいました。
QVGAの機種ではもちろんこの現象は発生しません。

ボタンクリック前


ボタンクリック後



Microsoft 高 DPI 対応アプリケーションの開発
Microsoft 高 DPI アプリケーションの記述方法
上記によると、プログラムで指定したサイズは96 dpi を想定したピクセル値なので、自分でスケーリングしなければならないようです。

画面の解像度(dpi)と画面のサイズを取得するには?と同じようにdpiを取得しスケーリング値を計算します。

'デバイスコンテキストを得る  
<DllImport("coredll.dll")> _  
Private Shared Function GetDC(ByVal hwnd As IntPtr) As IntPtr  
End Function  

'デバイスコンテキストを解放する  
<DllImport("coredll.dll")> _  
Private Shared Function ReleaseDC(ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As Boolean  
End Function  

'指定されたデバイスに関するデバイス固有情報を取得します。  
<DllImport("coredll.dll")> _  
Private Shared Function GetDeviceCaps _  
(ByVal hdc As IntPtr, ByVal nIndex As Integer) As Integer  
End Function  

Private Const LOGPIXELSX As Integer = 88    '論理インチ当たりの画面の水平方向のピクセル数  
Private Const LOGPIXELSY As Integer = 90    '論理インチ当たりの画面の垂直方向のピクセル数  


Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _  
Handles Button2.Click  

Dim ScreenHdc As IntPtr = GetDC(Me.Handle)

'DPI  
Dim dpiX As Integer = GetDeviceCaps(ScreenHdc, LOGPIXELSX)
Dim dpiY As Integer = GetDeviceCaps(ScreenHdc, LOGPIXELSY)

'SCALE
Dim scaleX As Single = dpiX / 96
Dim scaleY As Single = dpiY / 96

Dim width As Integer = Convert.ToInt32(Math.Round(100 * scaleX))
Dim height As Integer = Convert.ToInt32(Math.Round(100 * scaleY))
Me.Panel1.Size = New Size(width , height )
End Sub  

.NET(Mobile) 画面の解像度(dpi)と画面のサイズを取得するには?

画面の解像度(dpi)と画面のサイズを取得するにはGetDeviceCaps APIを使用します。

'デバイスコンテキストを得る
<DllImport("coredll.dll")> _
Private Shared Function GetDC(ByVal hwnd As IntPtr) As IntPtr
End Function

'デバイスコンテキストを解放する
<DllImport("coredll.dll")> _
Private Shared Function ReleaseDC(ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As Boolean
End Function

'指定されたデバイスに関するデバイス固有情報を取得します。
<DllImport("coredll.dll")> _
Private Shared Function GetDeviceCaps _
(ByVal hdc As IntPtr, ByVal nIndex As Integer) As Integer
End Function

Private Const HORZRES As Integer = 8   '画面の幅 (ピクセル単位)
Private Const VERTRES As Integer = 10  '画面の高さ (ピクセル単位)
Private Const LOGPIXELSX As Integer = 88    '論理インチ当たりの画面の水平方向のピクセル数
Private Const LOGPIXELSY As Integer = 90    '論理インチ当たりの画面の垂直方向のピクセル数


Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button2.Click

Dim ScreenHdc As IntPtr = GetDC(Me.Handle)

'SCREEN SIZE
Dim screenX As Integer = GetDeviceCaps(ScreenHdc, HORZRES)
Dim screenY As Integer = GetDeviceCaps(ScreenHdc, VERTRES)


'DPI
Dim dpiX As Integer = GetDeviceCaps(ScreenHdc, LOGPIXELSX)
Dim dpiY As Integer = GetDeviceCaps(ScreenHdc, LOGPIXELSY)

ReleaseDC(Me.Handle, ScreenHdc)

MessageBox.Show(String.Format("screenX:{0}、screenY:{1}、dpiX:{2}、dpiY:{3}",screenX,screenY, dpiX, dpiY))
End Sub



WS007SH、X04HTでは以下の値が返りました。
screenX:480
screenY:640
dpiX:192
dpiY:192

CASIO DT-5200
QVGA
screenX:480
screenY:640
dpiX:96
dpiY:96
VGA
screenX:240
screenY:320
dpiX:96
dpiY:96

.NET(Mobile) デバイス プラットフォームを取得するには?(使えない!?)

Microsoftに方法 : デバイス プラットフォームを取得する方法があったので、ついでに試してみました。
Private Shared SPI_GETPLATFORMTYPE As System.UInt32 = 257

<DllImport("coredll.dll", EntryPoint:="SystemParametersInfo")> _
Friend Shared Function SystemParametersInfo _
(ByVal uiAction As System.UInt32, _
ByVal uiParam As System.UInt32, _
ByVal pvParam As System.Text.StringBuilder, _
ByVal fWinIni As System.UInt32) As Boolean
End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button1.Click
Dim buffer As New System.Text.StringBuilder(200)
SystemParametersInfo(SPI_GETPLATFORMTYPE, 200, buffer, 0)
MessageBox.Show(buffer.ToString)
End Sub


結果は
W-ZERO3(WS007SH)、X04HTともに「POCKET PC」が返ります。


Windows Mobile 6.0では以下の3つのEditionがあります。
Windows Mobile 6 Professional Edition …比較的大型のタッチスクリーンを搭載し、必須ではないが、多くの場合、QWERTYキーボードを備える。
Windows Mobile 6 Standard Edition …Windows Smartphoneの後継で、タッチスクリーンを搭載しない
Windows Mobile 6 Classic …電話機能がないPPCデバイスの後継。


Windows Mobile 5.0では以下の3つのEditionがあります。
Windows Mobile 5.0 for Smartphon
Windows Mobile 5.0 for Pocket PC Phone Edition
Windows Mobile 5.0 for Pocket PC

Windows Mobile 6とWindows Mobile 5.0は以下のような対応になるようです。
Windows Mobile 6Windows Mobile 5.0
Professional EditionSmartphon
Standard EditionPocket PC Phone Edition
ClassicPocket PC



W-ZERO3はSmartPhoneが返ってきそうなのですが、Willcomが特殊で「POCKET PC」が返るそうです。
X04HTはWindowsMobile6.0以降はEditionにかかわらず、すべて「POCKET PC」が返るそうです。


つまり使えないってこと!?