手机软件开发入门 - 中国象棋(2)090311
认识 windows mobile 的窗口部件
为了查阅MSDN、沟通交流,我们先来认识一下windows mobile的UI部分。如下图,我们需要搞清楚几个基本的概念:
- SIP - soft input panel, 软输入面板,就是输入法切换面板。
- Task bar,任务条,用来显示程序名称标题,选择程序,退出程序。
- Menu bar也叫Soft key bar或者Command bar,用来显示软按键菜单。
有了这些概念,以后再看文档就容易看懂了。比如要想知道如何隐藏输入法面板,就可以google一下“hide SIP windows mobile”来查找了。
全屏显示棋盘
手机屏幕很小,比如QVGA才有240x320像素,为了好看些,我们的象棋程序需要占用整个手机屏幕,也就是全屏显示。所以我们来研究一下windows mobile的全屏显示技术。
总体来说,要把一个窗口全屏显示,需要下面的步骤:
- 调用SHFullScreen()隐藏SIP, Task bar。
- 调用ShowWindow()隐藏Menu bar或者用MoveWindow()把window bar移出屏幕。用MoveWindow()的作用是保留soft key能接收消息。
- 调用MoveWindow()修改窗口的位置和大小,以便全屏显示。
要把一个对话框全屏显示,需要下面的步骤:
- 调用函数SHInitDialog()设置dwFlags为SHIDIF_FULLSCREENNOMENUBAR。
- 调用MoveWindow()设置对话框大小为整个屏幕的大小。
- 调用SetForegroundWindow()设置对话框为前景窗口。
- 调用SHFullScreen()隐藏Task bar和SIP bar。
或者保留menu bar,只是把它移出到屏幕外,以便接收soft key消息:
- 调用函数SHInitDialog()设置dwFlags为SHIDIF_SIZEDLGFULLSCREEN。
- 调用SHFullScreen()隐藏Task bar和SIP bar。
- 调用SetWindowPos()移出Menu bar。
- 调用MoveWindow()设置全屏的对话框。
参考资料:
- http://support.microsoft.com/kb/266244/en-us/
- window mobile 6 sdk的sample "Full Screen".
(欢迎转载,转载请注明来源和作者:杨波)
代码:
// cchess_teacher.cpp : 定义应用程序的入口点。 // #include "stdafx.h" #include "cchess_teacher.h" #define MAX_LOADSTRING 100 // 全局变量: HINSTANCE g_hInst; // 当前实例 HWND g_hWndMenuBar; // 菜单栏句柄 HBITMAP g_hBoard; // 棋盘位图句柄 BOOL g_bFullScreen; int g_iMenuHeight; // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE, LPTSTR); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); void LoadImages(HINSTANCE hInst); void UnloadImages(); void DrawBoard(HDC hdc); void FullScreen ( HWND hWnd, // In: Window BOOL bFullScreen // In: TRUE = Size to full screen. FALSE = Undo ); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; LoadImages(hInstance); // 执行应用程序初始化: if (!InitInstance(hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable; hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CCHESS_TEACHER)); // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } UnloadImages(); return (int) msg.wParam; } // // 函数: MyRegisterClass() // // 目的: 注册窗口类。 // // 注释: // ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CCHESS_TEACHER)); wc.hCursor = 0; wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = szWindowClass; return RegisterClass(&wc); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 g_hInst = hInstance; // 将实例句柄存储在全局变量中 #if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP) // 在应用程序初始化期间,应调用一次 SHInitExtraControls 以初始化 // 所有设备特定控件,例如,CAPEDIT 和 SIPPREF。 SHInitExtraControls(); #endif // WIN32_PLATFORM_PSPC || WIN32_PLATFORM_WFSP LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_CCHESS_TEACHER, szWindowClass, MAX_LOADSTRING); #if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP) //如果它已经在运行,则将焦点置于窗口上,然后退出 hWnd = FindWindow(szWindowClass, szTitle); if (hWnd) { // 将焦点置于最前面的子窗口 // “| 0x00000001”用于将所有附属窗口置于前台并 // 激活这些窗口。 SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001)); return 0; } #endif // WIN32_PLATFORM_PSPC || WIN32_PLATFORM_WFSP if (!MyRegisterClass(hInstance, szWindowClass)) { return FALSE; } hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } #ifdef WIN32_PLATFORM_PSPC // 使用 CW_USEDEFAULT 创建主窗口时,将不会考虑菜单栏的高度(如果创建了一个 // 菜单栏)。因此,我们要在创建窗口后调整其大小 // 如果菜单栏存在 if (g_hWndMenuBar) { RECT rc; RECT rcMenuBar; GetWindowRect(hWnd, &rc); GetWindowRect(g_hWndMenuBar, &rcMenuBar); g_iMenuHeight = rcMenuBar.bottom - rcMenuBar.top; rc.bottom -= g_iMenuHeight; MoveWindow(hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, FALSE); } #endif // WIN32_PLATFORM_PSPC ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; SIZE size; TCHAR msg[256] = L""; RECT rect; static SHACTIVATEINFO s_sai; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_HELP_ABOUT: DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About); break; case IDM_FULLSCREEN: FullScreen(hWnd, true); break; #ifdef WIN32_PLATFORM_PSPC case IDM_OK: SendMessage (hWnd, WM_CLOSE, 0, 0); break; #endif // WIN32_PLATFORM_PSPC default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_CREATE: #ifdef SHELL_AYGSHELL SHMENUBARINFO mbi; memset(&mbi, 0, sizeof(SHMENUBARINFO)); mbi.cbSize = sizeof(SHMENUBARINFO); mbi.hwndParent = hWnd; mbi.nToolBarId = IDR_MENU; mbi.hInstRes = g_hInst; if (!SHCreateMenuBar(&mbi)) { g_hWndMenuBar = NULL; } else { g_hWndMenuBar = mbi.hwndMB; } // 初始化外壳程序激活信息结构 memset(&s_sai, 0, sizeof (s_sai)); s_sai.cbSize = sizeof (s_sai); #endif // SHELL_AYGSHELL break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... DrawBoard(hdc); EndPaint(hWnd, &ps); // debug GetWindowExtEx(hdc, &size); wsprintf(msg, L"win ext: x=%d, y=%d/n", size.cx, size.cy); OutputDebugString(msg); GetViewportExtEx(hdc, &size); wsprintf(msg, L"viewport ext: x=%d, y=%d/n", size.cx, size.cy); OutputDebugString(msg); wsprintf(msg, L"screen: cx=%d, cy=%d/n", GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); OutputDebugString(msg); GetWindowRect(hWnd, &rect); wsprintf(msg, L"win rect: left=%d, top=%d, right=%d, bottom=%d/n", rect.left, rect.top, rect.right, rect.bottom); OutputDebugString(msg); SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, FALSE); wsprintf(msg, L"work area: left=%d, top=%d, right=%d, bottom=%d/n", rect.left, rect.top, rect.right, rect.bottom); OutputDebugString(msg); break; case WM_DESTROY: #ifdef SHELL_AYGSHELL CommandBar_Destroy(g_hWndMenuBar); #endif // SHELL_AYGSHELL PostQuitMessage(0); break; case WM_ACTIVATE: // 向外壳程序通知我们的激活消息 SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE); break; case WM_SETTINGCHANGE: SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai); break; case WM_HOTKEY: switch(HIWORD(lParam)) { case VK_TSOFT1: case VK_TSOFT2: { // if we are in full screen mode we want to exit // when the user presses a softkey. if (g_bFullScreen) { //SendMessage(GetDlgItem(hWnd,IDC_EDIT), WM_SETTEXT, 0, (LPARAM)L"[Softkey] Exiting Full Screen"); FullScreen(hWnd, FALSE); } } break; } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “关于”框的消息处理程序。 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: #ifdef SHELL_AYGSHELL { // 创建一个“完成”按钮并调整其大小。 SHINITDLGINFO shidi; shidi.dwMask = SHIDIM_FLAGS; shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_EMPTYMENU; shidi.hDlg = hDlg; SHInitDialog(&shidi); } #endif // SHELL_AYGSHELL return (INT_PTR)TRUE; case WM_COMMAND: #ifdef SHELL_AYGSHELL if (LOWORD(wParam) == IDOK) #endif { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; case WM_CLOSE: EndDialog(hDlg, message); return (INT_PTR)TRUE; } return (INT_PTR)FALSE; } // yangbo // void LoadImages(HINSTANCE hInst) { g_hBoard = LoadBitmap(hInst, (LPCWSTR) IDB_BOARD); } void UnloadImages() { if(g_hBoard != NULL) { DeleteObject(g_hBoard); } } void DrawBoard(HDC hdc) { HDC hMemDC; hMemDC = CreateCompatibleDC(hdc); SelectObject(hMemDC, g_hBoard); BitBlt(hdc, 0, 0, 240, 320, hMemDC, 0, 0, SRCCOPY); DeleteDC(hMemDC); } // full screen: ms-help://MS.WindowsMobile.6/WindowsMobile6SDK/html/d4cb5890-0d2c-4c6d-adbb-672c7acf3680.htm // 获取工作区域大小:SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE); //screen: cx=240, cy=320 //win rect: left=0, top=26, right=240, bottom=294 //work area: left=0, top=26, right=240, bottom=320 // // FUNCTION: SizeFullScreen // // PURPOSE: Change the specified window size to full screen // void SizeFullScreen ( HWND hWnd, // In: Window BOOL bFullScreen // In: TRUE = Size to full screen. FALSE = Undo ) { RECT rc; if (bFullScreen) { // Full screen size SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); } else { // Normal size SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE); rc.bottom -= g_iMenuHeight; } MoveWindow( hWnd, rc.left, rc.top, rc.right, rc.bottom, FALSE); } // // FUNCTION: HideShellUI // // PURPOSE: Hide Shell UI components // void HideShellUI ( HWND hWnd, // In: Window BOOL bHide // In: FALSE to show. TRUE to hide. ) { DWORD dwState; dwState = bHide ? (SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON) : (SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON); // Show/Hide Shell UI SHFullScreen(hWnd, dwState); // We need to hide the tray manually for 2003 SE // and earlier versions of Smartphone. /*if (IsSmartphone2003SEOrOlder()) { HWND hwndTray = FindWindow(L"Tray", NULL); if (hwndTray) { HWND pos = bHide ? HWND_BOTTOM : HWND_TOP; SetWindowPos(hwndTray, pos, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } } */ } // // FUNCTION: SetSoftkeyBarForFullScreen // // PURPOSE: Setup the softkey for full screen/non full screen mode // void SetSoftkeyBarForFullScreen ( HWND hwndSoftKeyBar, // In: Softkeybar BOOL bFullScreen // In: TRUE = set for full screen. FALSE = undo ) { if (bFullScreen) { // Move softkey bar off-screen. Don't hide it because // a hidden softkey bar will not receive key override // messages. SetWindowPos(hwndSoftKeyBar, NULL, -1, -1, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE ); } else { // Move softkey bar on-screen. int iSoftkeysHeight = g_iMenuHeight; SetWindowPos(hwndSoftKeyBar, NULL, 0, GetSystemMetrics(SM_CYSCREEN) - iSoftkeysHeight, GetSystemMetrics(SM_CXSCREEN), iSoftkeysHeight, SWP_NOZORDER | SWP_NOACTIVATE ); } // Override/Undo softkeys for key press notifications, so we can // display taskbar & softkeys on SK1/SK2 press in full screen. DWORD dwBits; dwBits = bFullScreen ? SHMBOF_NODEFAULT | SHMBOF_NOTIFY : 0; SendMessage(hwndSoftKeyBar, SHCMBM_OVERRIDEKEY, VK_TSOFT1, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, dwBits)); SendMessage(hwndSoftKeyBar, SHCMBM_OVERRIDEKEY, VK_TSOFT2, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, dwBits)); } // // FUNCTION: FullScreen // // PURPOSE: Change the specified window to full screen // void FullScreen ( HWND hWnd, // In: Window BOOL bFullScreen // In: TRUE = Size to full screen. FALSE = Undo ) { g_bFullScreen = bFullScreen; HideShellUI(hWnd, g_bFullScreen); SetSoftkeyBarForFullScreen(g_hWndMenuBar, g_bFullScreen); SizeFullScreen(hWnd, g_bFullScreen); }
手机软件开发入门 - 中国象棋(2)090311相关推荐
- 手机软件开发入门 - 中国象棋(1)090308
最近迷恋起中国象棋来了.我棋力很一般,但是总感觉人生如棋,每一个决定都会影响将来局势的发展.深思熟虑者,后势就比较占优.沉着应战,方显人生力量.刚好,2月份的时候把我的一部使用了快两年的三星普通手机换 ...
- 手机软件开发入门 [转]
昨天在<程序员>上看到一篇访谈文章,孟岩就3G手机软件采访科泰世纪的陈榕.看了后,第一个感觉就是陈榕没做过手机软件.其实"不知为不知"也无所谓,但陈榕扯了一堆&quo ...
- 第一章 软件开发入门引导及概述
第一章 软件开发入门引导及概述 前言 计算机系统是由硬件和软件组成,所谓硬件是指组成计算机系统的物理设备,包括电子的.机械的.磁的.光的设备的总和. 我们的电脑.手机.电子设备都算一个小的计算机. 而 ...
- 从事手机软件开发需要掌握什么知识
与其说事先掌握好什么知识,不如说有没有不断学习掌握新知识的心态和思想准备.体力准备更重要.给自己找准一个方向最重要. 从开发的角度上简单的说手机软件可以分成应用软件.用户界面.操作系统.底层与设备驱动 ...
- (转载)H5 手机 App 开发入门:概念篇
H5 手机 App 开发入门:概念篇 一.H5 的含义 二.原生应用 2.1 概念 2.2 优点 2.3 缺点 三.Web 应用 3.1 概念 3.2 优点和缺点 3.3 Web APP 的劣势 3. ...
- 开源力作, 使用 C# 开发的中国象棋
Chess Chess 是一个基于 C# WPF开发的功能完善的中国象棋软件, 已开源全部源码,开箱即用.代码中含有大量注释,能够快速理解程序流程.可用于二次开发和学习. 功能特性 1. 人机对战,测 ...
- Android手机软件开发的前景
Android手机软件开发的前景 今天是3G 的年代,中国拥有超过7亿的手机用户,而全球更是将近50亿,这样一个庞大的用户市场.而随着运营商语音话费的下降,手机上的各类增值应用已经成为了这个行业各环节 ...
- 海思软件开发入门篇 (一)
标题 海思软件开发入门篇 (一) (第一次写博客,有错别字与写的不好的地方敬请谅解.) 加过很多群,也逛过很多论坛,很多人在问,第一次接触海思不知道从而入手,的确,现在一个SDK动不动上G,还 ...
- 手把手教你iPhone 3G手机软件开发
手把手教你iPhone 3G手机软件开发 "iPhone 是一款革命性的.不可思议的产品,比市场上其它任何移动电话整整领先了五年,"苹果公司首席执行官史蒂夫·乔布斯如是说,&quo ...
最新文章
- perfect book
- 教师课堂教学必备的100个妙招,总有一个适合你!
- PCI BAR设置过程
- Linux执行yum不显示时间图形,Linux停的yum命令详解(朝花夕拾)
- 控制游戏中物体的移动速度
- 用vmware-converter4把linux 迁移到ESX4.1中
- 牛客网Java刷题知识点之插入排序(直接插入排序和希尔排序)、选择排序(直接选择排序和堆排序)、冒泡排序、快速排序、归并排序和基数排序(博主推荐)...
- C语言试题十九之根据以下公式求p的值,结果由函数值带回。M与n为两个正整数,且要求m>n。 p=m!/n!(m-n)!
- ubuntu18.04 用xhell连接失败
- android 连续调用方法是,android – SwitchPreferences多次调用onPreferenceChange()方法
- Linux系统各个目录的一般作用
- PDFDOC365工具箱
- 良品铺子的2021:营收创新高后的“战术调整”
- 85. Maximal Rectangle最大矩形
- 【面试招聘】超强整理,非科班小硕的进击之路
- word转图片,pdf转图片,doc转图片,docx转图片
- time秒和年月日时分秒的转化
- 向U盘中安装Linux系统的经验(不是制作安装盘)
- NOIP 提高组 2012 / 洛谷P1080 国王游戏 题解
- oracle+ebs+om+流程,Oracle EBS OM Order is not eligible for booking