Windows Mobile

Türchen Nummer 24

Sollte man die Weihnachtsgeschenke für seine Lieben bereits gekauft haben, so kommt man meist zum eher unangenehmen Teil: Dem Verpacken.
Dies gilt jedoch auch für Anwendungen, die auf einem mobilen Gerät installiert werden sollen. Hierfür gibt es das CAB-Datei Format.
 
Um eine entsprechende Installationsdatei zu erstellen, nehmen wir einmal an, dass wir die zu verpackenden Dateien unter c:HelloWorld abgelegt haben.
Die Dateien, welche dort vorliegen müssen, sind die HelloWorld.exe, welche installiert werden soll, sowie die HelloWorld.inf Datei, welche die Informationen für den CabWizard vorbehält, um eine CAB-Datei erzeugen zu können.
Hier nun der Inhalt der INF-Datei dazu. Hierbei hat die Programmiersprache diesmal keine Relevanz:
[SOURCE FILE]
Name=CHelloWorld.cab
Path=C:HelloWorldHelloWorld.cab
AllowUninstall=TRUE
[Version]
Signature="$Chicago$"
CESignature="$Windows CE$"
Provider="Company"
[CEStrings]
AppName="HelloWorld"
InstallDir="%CE1%CHelloWorld"
[CEDevice]
ProcessorType=0
VersionMin=0.0
VersionMax=0.0
BuildMin=0
BuildMax=0
[SourceDisksNames]
1=,Source1,,
[SourceDisksFiles]
"HelloWorld.exe"=1
[CopyFiles1]
"HelloWorld.exe",,,0x00000001
[DestinationDirs]
CopyFiles1=0,"%CE1%HelloWorld"
[DefaultInstall]
CopyFiles=CopyFiles1
 
 
Wird nun auf der Kommandozeile der Befehl "c:Program FilesMicrosoft Visual Studio 9.0SmartDevicesSDKSDKToolscabwiz.exe" "Company HelloWorld2.inf" ausgeführt (Pfad ist natürlich hinsichtlich seinen Gegebenheiten anzupassen), so findet sich im entsprechenden Zielordner die CAB-Installationsdatei wieder.
Weitere Informationen zum CAB-Wizard erhalten Sie hier: http://msdn.microsoft.com/de-de/library/cc433670%28VS.71%29.aspx
Patrick & Peter
Advertisements
Windows Mobile

Türchen Nummer 23

So kurz vor weihnachten sollte der Weihnachtsbaum hell leuchten. Warum auch nicht dann die LED des Bluetoothmoduls des Gerätes zum Blinken bringen?
Nichts einfacher als das, in dem man das Bluetooth Modul aktiviert.

Dabei gilt zu beachten, dass dieses Beispiel nur auf Geräten funktioniert, die den Microsoft Bluetooth Stack verwenden.

C++

#include "bthutil.h"
#pragma comment(lib, "Bthutil.lib")

DWORD dwMode = 0;
BthGetMode(&dwMode);
if(dwMode==BTH_POWER_OFF || dwMode==BTH_CONNECTABLE)
{
    BthSetMode(BTH_DISCOVERABLE);
}



C#

In C# ist es auch an dieser Stelle nötig, mittels P/Invoke auf die nötige DLL zu zu greifen, um auf die entsprechenden Informationen zu erhalten.
Somit hier das Snippet:


public enum RadioMode
{
    Off = 0,
    Connectable = 1,
    Discoverable = 2
}

static class Program
{
    [DllImport("BthUtil.dll")]
    private static extern int BthGetMode(out RadioMode dwMode);

    [DllImport("BthUtil.dll")]
    private static extern int BthSetMode(RadioMode dwMode);

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [MTAThread]
    static void Main()
    {
        RadioMode rm = RadioMode.Off;
        BthGetMode(out rm);
        if (rm == RadioMode.Off || rm== RadioMode.Connectable)
        {
            BthSetMode(RadioMode.Discoverable);   
        }
    }
}

Patrick & Peter

Windows Mobile

Türchen Nummer 22

In vielen Fenstern und Wohnungen findet man zur Weihnachtszeit eine ganze Menge an Lichterketten und sonstiger beleuchteter Weihnachtsdekoration.
Das manuelle Einschalten dieser vielen Lichterketten und Lämpchen kann eine zeitraubende Beschäftigung werden.
Gleiches gilt auch für Windows Mobile Applikationen die durchgehend laufen sollen. Wenn der Anwender diese Applikationen manuell starten muss dauert dies natürlich auch eine Weile.
Wäre es nicht angenehmer wenn dies automatisch geschehen würde?
Mit folgendem Codeschnipsel kann aus der eigenen Anwendung heraus, beispielsweise per Optionsdialog, eine Autostartverknüpfung angelegt werden.

C++

//Dies ist eigentlich das gleiche Schnipsel wie Türchen Nummer 8
//jedoch wird diesmal die CSIDL_STARTUP verwendet.
//Autostart Ordner auslesen
WCHAR szShortcutPath[MAX_PATH*2] = L"";
SHGetSpecialFolderPath(NULL,szShortcutPath,CSIDL_STARTUP,0);
wcscat(szShortcutPath,L"\MeinShortcut.lnk");
//Modulnamen auslesen
WCHAR szModulePath[MAX_PATH*2] = L"";
GetModuleFileName(GetModuleHandle(NULL), szModulePath, MAX_PATH);
//Shortcut erstellen
SHCreateShortcut(szShortcutPath,szModulePath);



In C# ist es diesmal nicht notwendig P/Invoke zu nutzen, um an diese Informationen zu kommen. Die Klasse Environment hierfür reicht völlig.
Hier also das Snippet:

C#


[DllImport("coredll.dll")]
private static extern int SHCreateShortcut(StringBuilder szShortcut, StringBuilder szTarget);

[MTAThread]
static void Main()
{

   StringBuilder shortcut = new StringBuilder(System.Environment.GetFolderPath(Environment.SpecialFolder.Startup)+@"MeinShortcut.lnk");
   StringBuilder target = new StringBuilder(@"windowscalc.exe");
   SHCreateShortcut(shortcut, target);
}

Patrick & Peter

Windows Mobile

Türchen Nummer 21

Der große Vorteil eines digitalen Adventskalenders ist, dass man volle Kontrolle über alle Türchen
hat und niemand vorab schon mal die "24" öffnen kann.
Eine vollständige Kontrolle bspw. über sämtliche Tasten kann auch mal in einer Windows Mobile Applikation benötigt werden.
Das folgende Codeschnipsel zeigt wie man dies mit der AllKeys API bewerkstelligen kann.

C++

//Alle Tasten abfangen(bspw. in WM_CREATE)
AllKeys(TRUE);

//In WM_KEYDOWN und WM_KEYUP den WPARAM prüfen.
//Siehe http://msdn.microsoft.com/en-us/library/bb431750.aspx für Keycodes
case WM_KEYDOWN:
    OutputDebugString(L"WM_KEYDOWNn");
    //Behandlung für den Tastencode ist hier nicht aufgeführt
    HandleKey(wParam);
    break;
case WM_KEYUP:
    OutputDebugString(L"WM_KEYUPn");
    //Behandlung für den Tastencode ist hier nicht aufgeführt
    HandleKey(wParam);
    break;



Im verwaltetem Code ist es mehr Code nötig, um das gleiche Ziel zu erreichen. Das liegt daran, dass eine Windows Form generell die Verarbeitung von derlei Nachrichten intern bereits durchführt.
Um also auf die internen Window Messages zugreifen zu können, ist es nötig, eine Klasse zu erstellen, die von der Klasse MessageWindow ableitet. Zusätzlich ist auch das P/Invoke notwendig, um die AllKeys-Methode auf zu rufen.
Somit ist es diesmal für das Snippet nötig, eine Anwendung für intelligene Geräte anzulegen, welche eine Geräteanwendung darstellt.
Der Code is dann entsprechend ähnlich abzuändern:

C#


using Microsoft.WindowsCE.Forms;

public partial class MessageForm : Form
{
    [DllImport("coredll.dll", SetLastError = true)]
    static extern bool AllKeys(bool bAllKeys);
    
    MsgWindow msgWin;

    public MessageForm()
    {
        InitializeComponent();
        AllKeys(true);
        msgWin = new MsgWindow(this);
    }

}

public class MsgWindow : MessageWindow
{
    public const int WM_KEYDOWN = 0x0100;
    public const int WM_KEYUP = 0x0101;

    private MessageForm msgform;

    public MsgWindow(MessageForm msgform)
    {
        this.msgform = msgform;
    }

    protected override void WndProc(ref Message msg)
    {
        switch (msg.Msg)
        {
            case WM_KEYDOWN:
                MessageBox.Show("Key was down with WPARAM:" + ((int)msg.WParam).ToString() + "and LPARAM:" + ((int)msg.LParam).ToString());
                break;
            case WM_KEYUP:
                MessageBox.Show("Key was up with WPARAM:" + ((int)msg.WParam).ToString() + "and LPARAM:" + ((int)msg.LParam).ToString());
                break;
        }
        base.WndProc(ref msg);
    }
}

Mehr Informationen zur Klasse MessageWindow erhalten Sie hier:

http://msdn.microsoft.com/de-de/library/microsoft.windowsce.forms.messagewindow%28VS.80%29.aspx

Patrick & Peter

Windows Mobile

Türchen Nummer 20

Gerade in der Weihnachtszeit sind die Schaufenster derart mit Werbung oder Kunstschnee zugekleistert, das der Blick auf die schönen Dinge dahinter verwehrt ist.
Auch dies gilt für manche Windows Mobile Anwendung, die man im Vollbildmodus betreiben möchte.

C++

//Der folgende Code gilt für Win32 Anwendungen.
//Er ist im IDM_HELP_ABOUT Handler der WM_COMMAND Nachricht
//einer per Visual Studio 2008 Win32 Projekt für intelligente Geräte (Windowsanwendung)
//untergebracht. Der DialogBox Aufruf ist auskommentiert.
//Rückgängig gemacht werden sollte der Fullscrenn Code bspw. über ein Kontextmenu oder beim
//beenden der Applikation
//DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About);
//Fenster muss für SHFullScreen im Vordergrund sein
SetForegroundWindow(hWnd);
//SIP und Taskbar in den Hintergrund legen
SHFullScreen(hWnd,SHFS_HIDESIPBUTTON|SHFS_HIDETASKBAR);
//Die Menübar soll auch weg
HWND hwndMenu = SHFindMenuBar(hWnd);
//Erst die Menübarhöhe holen. Gilt auch für das Starmenü
RECT rcMenue;
GetWindowRect(hwndMenu, &rcMenue);
//Menübar verschieben
SetWindowPos(hwndMenu, NULL,-1, -1,0, 0,SWP_NOZORDER | SWP_NOACTIVATE);
//Jetzt muss unser Fenster noch neu positioniert werden
RECT rect;
GetWindowRect(hWnd,&rect);
rect.top -= rcMenue.bottom – rcMenue.top;
rect.bottom += rcMenue.bottom – rcMenue.top;
MoveWindow(hWnd,rect.left,rect.top,rect.right,rect.bottom,TRUE);



C#

Eine Anwendung zu erstellen, welche eine Vollbilddarstellung liefert ist mit Bordmitteln des .NET Compact
Frameworks bereits einfach realisierbar.
Dies geht sogar so einfach, dass nicht einmal ein Snippet hierfür notwendig ist.
Setzen Sie für die Vollbilddarstellung Ihrer Form einfach die zugehörige Eigenschaft WindowsState auf den
Wert FormWindowState.Maximized. Hierdurch »verschwindet« die Titelzeile Ihrer Anwendung.
Damit sich jedoch kein vielleicht im Hintergrund startendes Programm in den Vordergrund setzt und Ihre
Anwendung überlagert, sollten Sie gleichfalls die Eigenschaft TopMost der Form auf den Wert true setzten.
Wollen Sie gleichfalls die Menüzeile, welche Ihr Anwendungsmenü darstellt und meist auch die virtuelle
Tastatur aktiviert, deaktivieren, ist auch dies ganz einfach. Leider gibt es für das MainMenu keine Eigenschaft
»Enabled«, um dies zu ermöglichen. Stattdessen reicht es, wenn die Eigenschaft Menu der zugehörigen Form auf
den Wert null gesetzt wird, was auch dynamisch aus der Anwendung möglich ist.
Hierdurch wird die Zuweisung eines MainMenu zur Form entfernt, wodurch Sie eine komplette
Vollbilddarstellung Ihrer Anwendung erhalten. Wenn Sie nun Menu wieder das Objekt vom Typ MainMenu
zuweisen, haben Sie wieder Ihren Ursprungszustand hergestellt.

Patrick & Peter

Windows Mobile

Türchen Nummer 19

Wer dem Weihnachtstress ein wenig aus dem Weg gehen möchte vermeidet es am besten die Geschenke auf althergebrachte Weise in der Stadt oder sonstigen Einkaufläden zu besorgen.
Nichts ist entspannter als ein Einkaufbummel im Internet. Und wenn man die Einkauftour rechtzeitig beginn bekommt auch keinen Stress mit den Lieferzeiten.
Um aber trotzdem an sein Paket zu kommen muss man natürlich seine eigene Adresse mitteilen.
Gleiches gilt auch für Anwendung die auf Netzwerkdienste zugreifen. Oftmals muss die Anwendung die eigene IP Adresse nicht kennen, da es durch die zugrunde liegenden Protokolle automatisch passiert. Ab und an kann es aber vorkommen dass diese Information benötigt wird.
Dazu kann das folgende Codeschnipsel verwendet werden:

C++

#include "iphlpapi.h"
#pragma comment(lib, "Iphlpapi.lib")

//Wir listen mal etwas mehr auf als nur die aktuellen IPs.
//Adapter Information anlegen
PIP_ADAPTER_INFO pAdapterInfo;
ULONG lRetLen = sizeof(PIP_ADAPTER_INFO);
//Benötigte Speichergrösse holen
DWORD dwRet = GetAdaptersInfo(NULL,&lRetLen);
//Informationen zu allen Adaptern holen
pAdapterInfo = (PIP_ADAPTER_INFO) malloc (lRetLen);
dwRet = GetAdaptersInfo(pAdapterInfo,&lRetLen);
if(dwRet == ERROR_SUCCESS)
{
    //Informationen nur für den aktuellen Adapter
    PIP_ADAPTER_INFO pCurrentAdapter = pAdapterInfo;
    while (pCurrentAdapter != NULL )
    {
        //Systemindex
        printf("Adapterindex: %in",pCurrentAdapter->Index);
        //Beschreibung
        printf("Beschreibung: %sn",pCurrentAdapter->Description);
        //IP Addresse
        printf("IP: %sn",pCurrentAdapter->IpAddressList.IpAddress.String);
        //Gateway
        printf("Gateway: %sn",pCurrentAdapter->GatewayList.IpAddress.String);
        //Subnet
        printf("Subnet: %sn",pCurrentAdapter->IpAddressList.IpMask.String);
        //Erweiterte IP Infos anlegen
        PIP_PER_ADAPTER_INFO pPerAdapterInfo;
        lRetLen = sizeof(PIP_PER_ADAPTER_INFO);
        //Benötigte Speichergrösse holen
        dwRet = GetPerAdapterInfo(pCurrentAdapter->Index,NULL,&lRetLen);
        //Erweiterte IP Infos abfragen    
        pPerAdapterInfo = (PIP_PER_ADAPTER_INFO) malloc (lRetLen);
        dwRet = GetPerAdapterInfo(pCurrentAdapter->Index,pPerAdapterInfo,&lRetLen);
        //DNS1
        printf("DNS: %sn",pPerAdapterInfo->DnsServerList.IpAddress.String);
        //DNS2
        if(pPerAdapterInfo->DnsServerList.Next != NULL)
            printf("DNS2: %sn",pPerAdapterInfo->DnsServerList.Next->IpAddress.String);
        //Interface anlegen
        MIB_IFROW IfRow;
        memset( &IfRow, NULL, sizeof( MIB_IFROW ) );
        //Index zum abfragen setzen
        IfRow.dwIndex = pCurrentAdapter->Index;
        //Interface abfragen
        GetIfEntry(&IfRow);
        //MAC Adresse
        printf("MAC: %02x-%02x-%02x-%02x-%02x-%02xn",IfRow.bPhysAddr[0], IfRow.bPhysAddr[1], IfRow.bPhysAddr[2], IfRow.bPhysAddr[3], IfRow.bPhysAddr[4], IfRow.bPhysAddr[5]);
        //Den Namen(ClassID) brauchen wir auch…
        printf("ClassID: %sn",pCurrentAdapter->AdapterName);
        //Nächster Adapter
        pCurrentAdapter = pCurrentAdapter->Next;
    }
}



C#

In C# geht dies ebenfalls ganz einfach, auch wenn es wild aussieht:

using System.Net;

IPHostEntry enty = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ipadress in enty.AddressList)
{
    Console.WriteLine("IP: " + ipadress.ToString());   
}

Patrick & Peter

Windows Mobile

Türchen Nummer 18

 Freitag, 18. Dezember 2009

Nach einem längeren Abend am Glühweinstand kann es in seltenen Fällen dazu kommen, dass man seinen eigenen Namen am nächsten Morgen vergessen hat.
Gut, wenn dieser im mobilen Gerät gespeichert ist.
Das folgende Beispiel funktioniert natürlich nur dann, wenn der Benutzername in den Besitzerinformationen hinterlegt wurde.

C++

//State & Notification Broker Header Datei
#include "snapi.h"
//Registry Hilfsfunktionen
#include "regext.h"

//Per Registry Helfer Funktion und den State&Notification Broker Konstanten
//die Besitzerinformationen auslesen. Setzt natürlich voraus das der Anwender diese Informationen auch eingegeben hat.
TCHAR szUserName[MAX_PATH] = L"";
if(RegistryGetString(SN_OWNERNAME_ROOT,SN_OWNERNAME_PATH,SN_OWNERNAME_VALUE,szUserName,MAX_PATH)==S_OK)
    _tprintf(L"Username: %sn",szUserName);
else
    _tprintf(L"Fehler bei RegistryGetStringn");



C#

Mittels SnAPI ist das Auslesen mittels managed Code ganz einfach, wenn zuvor die Verweise zu den Bibliotheken Microsoft.WindowsMobile und Microsoft.WindowsMobile.Status hinzugefügt wurden.

Somit besteht das Snippet dann wieder aus einer Zeile ausführbarem Code:

using Microsoft.WindowsMobile.Status;

Console.WriteLine((string)SystemState.GetValue(SystemProperty.OwnerName));

Patrick & Peter