WinCE应用程序部分学习总结

 

WinCE应用程序部分学习总结

       到新公司来4个多月了,最近做的基于WinCE的程序也算是基本完成了,所以想对于最近学习的一些东西做一个归纳总结。其实对于WinCE的应用来说,大多数情况都是界面开发,所以对于想学底层的人,对于这一部分作为一个了解即可,至少要会写一个简单的对话框程序来测试你的底层驱动。想做一个比较炫的界面是非常复杂的,所以以下的方法都是一些简单的界面程序设计。
      
首先,需要理解的一点是,在WinCE中,不管是对话框,按键,以及各种对话框,他们其实都是一个窗口。理解这一点,对于初学者来说还是很重要的,这也就意味着我们可以像绘制普通窗口那样去绘制按键,或者ListBox的背景,无非你要做的就是获得这些控件的HDC

       Ok,还有需要提醒的一点就是,在程序中也许你会用到MessageBox,或者模态的对话框,这两者的使用都会使你主窗口的消息得不到处理,所以你的主窗口的界面就会得不到刷新。解决办法就是换成非模态的对话框即可。下面就对一些我用到的界面设计中的方法作一个总结(嘿嘿,对了,我都是用Win32写的,不会MFC,我想其实道理也都差不多):

 

一.绘制界面背景:

呵呵,也许眨一看,觉得无非绘制背景嘛,加载一张图片,然后Bitbit上去就可以了。但是当我们需要在一个背景上添加各种图片,或者需要移动的线条,or你要自己实现一个漂亮的滚动条。那么问题就出现了,每当你去刷新界面的时候,屏幕会闪烁的非常厉害,也许你可以在刷新的时候,只刷新你需要更新的那一部分,但是当你需要刷新整个界面的时候,那么这个办法就不行了。So,双缓冲是解决这个问题最好的方法。双缓冲的原理,大家可以Google一下(抵制baidu,支持Google)。直接贴代码:

/***********************************************************************************************

* 函数介绍:双缓冲绘制按键背景函数,由于要频繁调用该方法,所以独立出来该函数

* 输入参数:hWnd:按键句柄, hBtnmap:按键背景图, x y:按键大小, iOffsetX iOffsetY:偏移量

* 输出参数:没得!

* 返回值 : 也没得!

***********************************************************************************************/

void HelloDrawBk(HWND hWnd, HBITMAP hBtnMap, int x, int y, int iOffsetX, int iOffsetY)

{

     HDC     hdc;                   //一个DC

     HDC     hdcMem;                //两个DC

     HDC     hdcMemBuf;             //三个DC,呀!怎么成三缓冲了。

     RECT    rect;

     HBITMAP hBitmap;

     HBITMAP hOldBmp1;

     HBITMAP hOldBmp2;

 

     hdc = GetDC(hWnd);       //嘿嘿。。这里是我绘制按键背景的函数,所以我要取得他的HDC

    

//创建第一个内存DC

hdcMem = CreateCompatibleDC(NULL);            

     hBitmap = CreateCompatibleBitmap( hdc, x, y);  //创建缓冲位图,先把图画到这张空白位图上

 

     //创建第二个内存DC

     hdcMemBuf = CreateCompatibleDC(NULL );      

 

     //将空白位图选进第一缓冲区

     hOldBmp1 = ( HBITMAP )SelectObject( hdcMem, hBitmap);        

 

     //用背景色刷一下

     GetClientRect(hWnd, &rect);

     FillRect( hdcMem, &rect, NULL );            

 

     //将背景图贴上去,选择背景的起始位置,这里的背景坐标是由按键在背景图上的位置所决定的!

     hOldBmp2 = ( HBITMAP )SelectObject( hdcMemBuf, hBackBitMap);

     BitBlt( hdcMem, 0, 0, x, y, hdcMemBuf, iOffsetX, iOffsetY, SRCCOPY);

     SelectObject( hdcMemBuf, hOldBmp2 );

 

     //把按键图贴上去

     hOldBmp2 = ( HBITMAP )SelectObject( hdcMemBuf, hBtnMap);

 

     //该函数可以实现透明背景

     TransparentBlt(hdcMem, 0, 0, x, y, hdcMemBuf, 0, 0, x, y, RGB(255,0,0));

 

     //最后画到目的DC    这个HDC应该不叫缓冲吧,那么我们还是叫他双缓冲。

     BitBlt( hdc, 0, 0, x, y, hdcMem, 0, 0,SRCCOPY); 

 

     //结束操作

     SelectObject( hdcMem, hOldBmp1 );           //友情提示:不选出来要内存泄漏的哦!

     SelectObject( hdcMemBuf, hOldBmp2 );        //友情提示:要全部选出来哦!

     DeleteDC( hdcMem );

     DeleteDC( hdcMemBuf );

     DeleteObject( hBitmap );

     ReleaseDC (hWnd, hdc);

}

 

Notice

由于是我们自己绘制窗口背景,所以在窗口消息中应该加上

case WM_ERASEBKGND:                                                              

        break;

这样窗口就不会自己去刷新背景了。

 

恩恩......!这样你的界面就不会闪了。俗话说:有好处就有坏处(这真的是谚语?),双缓冲对资源的耗费还是比较大的,如果你用一个Timer去刷新背景,那我就不保证你的程序一定正常咯。So,在写程序的时候,我们尽量不用Timer去刷新背景,在程序真正需要刷新的时候我们再去刷新屏幕,这个就需要由你的程序来决定怎么刷新咯。但是,用双缓冲的时候,一定,确定,务必,肯定,要记着这一点(咱是吃过亏的!)。

 

二.绘制按键背景。

既然我们会画背景咯,恩.......那么我们怎么绘制按键背景了,还要按下去和弹起来的时候不一样。MFC好像很简单就实现了,但是Win32就比较复杂一点咯。首先,按键消息,WM_LBUTTONDOWNWM_LBUTTONUP,我们获取这个消息就可以了,但是如果主窗口有很多按键了?那么,我们就需要SetWindowsLong这个函数了(没用过的,查MSDN去,没有MSDNbaidu去!错了!Google去,抵制baidu支持Google!)

1、 创建按键:

     //创建按键,创建的时候必须加上BS_OWNERDRAW消息,表示我们自绘按键

     hPreBTN   = CreateWindow (TEXT ("BUTTON"), NULL,

         BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_OWNERDRAW ,

12, 35, 48, 40, hMainWnd, (HMENU)IDC_PreBTN, hMainInst, NULL);

2、 创建好按键以后我们需要:

SetWindowLong (hXxBtnWnd, GWL_WNDPROC, (long)XxBtnProc);

    该函数把XxBtnXX按键)的消息传递给了我们自定义的函数XxBtnProc来处理.

3、 实现XxBtnProc函数:

 /***********************************************************************************************

* 函数介绍:Xx按键消息处理函数,绘制Xx按键背景

* 输入参数:自己看!

* 输出参数:没得!

* 返回值 : 自己看!

***********************************************************************************************/

LRESULT WINAPI XxBtnProc (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)

{

 

     switch (wMsg)

     {

     case WM_LBUTTONDOWN:                                      //按下

               

                //这个函数就在上面,绘制背景的,莫要说不认识我!

         HelloDrawBk (hWnd, hXxBitMap1, 40, 40, 10, 5);

         break;

 

     case WM_LBUTTONUP:                                        //起来

                HelloDrawBk (hWnd, hXxBitMap2, 40, 40, 10, 5); 

         break;

     }

 

     //返回主窗口函数,不然主窗口得不到处理  不返回我试试!郁闷死你娃!5555555555555.....

     return DefWindowProc(hWnd, wMsg, wParam, lParam); 

}

 

4、 最后,你还需要在WM_PATINT消息里面绘制XxBtn的背景,不然按键没有初始背景。

    如果需要实现长按这些效果,那么可以设定一个Timer来实现(理论上是这样的,没做过!)。

三.自绘ListBox

这部分,我也只是实现了简单的背景颜色,和字体颜色的改变,想绘制ListBox的背景还没有找到很好的方法。直接贴代码:

LRESULT CALLBACK ListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

     HDC hdc;

     int wmId, wmEvent;

     PAINTSTRUCT ps;

     int i = 0;

     int iCurSlec;

     TCHAR tmpBuffer[256];

     TCHAR szOut [256];

 

     HBRUSH hbrBack;

 

     switch (message)

     {

     case WM_COMMAND:

         wmId    = LOWORD(wParam);

         wmEvent = HIWORD(wParam);

 

         // Parse the menu selections:

         switch (wmEvent)

         {

                //这个是ListBox窗口的双击消息

         case LBN_DBLCLK:

              iPlaySlec = SendDlgItemMessage (hWnd, IDC_LISTBOX, LB_GETCURSEL, 0, 0);

                        

                        //重新更新一下ListBox

              InvalidateRect(    hListboxWnd, NULL, FALSE); 

              break;

 

                //这个是ListBox窗口的单击消息

         case LBN_SELCHANGE:

 

                        //重新更新一下ListBox

              InvalidateRect(    hListboxWnd, NULL, FALSE);

              break;

         }

         break;

 

     case WM_CREATE:

          

           //创建一个ListBox窗口,LBS_OWNERDRAWVARIABLE指明是我们自绘ListBox,必须有该风格

        hListboxWnd = CreateWindow (TEXT ("LISTBOX"), NULL,

WS_VSCROLL |  WS_VISIBLE | WS_CHILD | WS_BORDER | WS_CHILD

| LBS_NOTIFY | LBS_HASSTRINGS | LBS_OWNERDRAWVARIABLE ,

               0, 0, 260, 325, hWnd, (HMENU)IDC_LISTBOX, hMainInst, NULL);

               

                //添加一些选项进去,作为测试用

         while ( i < 50)

         {

              i ++ ;

wsprintf (szOut, TEXT ("%d%d%d"), i, 0, 0);

 

// LB_ADDSTRING,添加一个选项

              SendDlgItemMessage (hWnd, IDC_LISTBOX, LB_ADDSTRING, 0, (LPARAM)szOut);

         }

         break;

 

     case WM_PAINT:

         RETAILMSG(TRUE, (TEXT("ListWindow: WM_PAINT!/r/n")));

         hdc = BeginPaint(hWnd, &ps);

          EndPaint(hWnd, &ps);

         break;

 

     case WM_ERASEBKGND:                                                              

         break;

 

     //控制ListBox选项的大小!

case WM_MEASUREITEM:

         LPMEASUREITEMSTRUCT lpmis;

         lpmis=(LPMEASUREITEMSTRUCT)lParam;

         lpmis->itemHeight=20;

         break;

 

        //绘制ListBox消息,在这里实现ListBox单个选项的绘制

case WM_DRAWITEM:

         LPDRAWITEMSTRUCT lpdis;

         lpdis=(LPDRAWITEMSTRUCT)lParam;

 

         iCurSlec = SendDlgItemMessage (hWnd, IDC_LISTBOX, LB_GETCURSEL, 0, 0);

         SendMessage(lpdis->hwndItem,LB_GETTEXT,lpdis->itemID,(LPARAM)tmpBuffer);

         SelectObject(lpdis->hDC,   hFont);  

                

                //改变单双数选项的背景色

         if (lpdis->itemID & 0x01)

              hbrBack = CreateSolidBrush (RGB (198, 233, 253));

         else

              hbrBack = CreateSolidBrush (RGB (200, 230, 250));

         FillRect (lpdis->hDC, &lpdis->rcItem, hbrBack);

 

                //实现选择,选中和未选的选项字体的不同颜色

         if (lpdis->itemID == iCurSlec)

         {

              hbrBack = CreateSolidBrush (RGB (0, 51, 204));

              FillRect (lpdis->hDC, &lpdis->rcItem, hbrBack);

 

              SetBkMode(lpdis->hDC,   TRANSPARENT);

              SetTextColor(lpdis->hDC,   RGB(0xff, 0xff, 0x00));

         }

         else if (lpdis->itemID == iPlaySlec)

         {

              SetBkMode(lpdis->hDC,   TRANSPARENT);

              SetTextColor(lpdis->hDC,   RGB(0xff, 0x00, 0xff));

         }

         else

         {

              SetBkMode(lpdis->hDC,   TRANSPARENT);

              SetTextColor(lpdis->hDC,   RGB(0x00, 0x00, 0xaa));

         }

                 

          //显示

         ExtTextOut(lpdis->hDC,0,((lpdis->rcItem.top + lpdis->rcItem.bottom)/2 - 10),

0, NULL, tmpBuffer,wcslen(tmpBuffer), NULL);  

         DeleteObject(hbrBack);

         break;

 

     default:

         return DefWindowProc(hWnd, message, wParam, lParam);        

     }

}

 

杂七杂八:

1、如果你需要在窗口中相应双击按键,那么你需要在注册窗口的时候加上 CS_DBLCLKS风格。

2、如果你需要改变窗口的大小,你可以用SetWindowPos来实现,下面的方法可以实现全屏:

LONG    nFullWidth=GetSystemMetrics(SM_CXSCREEN);  

LONG    nFullHeight=GetSystemMetrics(SM_CYSCREEN);

SetWindowPos(hDisplayWnd,   HWND_TOPMOST, 0, 0, nFullWidth, nFullHeight, SWP_SHOWWINDOW);

3、如果你想实现字体的背景透明:

SetBkMode(hDC, TRANSPARENT);

SetTextColor(hDC, RGB(0xff, 0x00, 0xff));

4、如果你想实现一个特定形状的图形,比如圆形,方形,那么你可以设计一个方形的图片,然后在周围填充上一种特定的颜色作为背景色,比如255的全红色,然后调用函数:

TransparentBlt(hdcMem, 0, 0, x, y, hDc, 0, 0, x, y, RGB(255,0,0));//bmp的图片,其他图片不知道!

5、如果你要使用非模态对话框记得在消息处理过程中加上IsDialogMessage

while (GetMessage(&msg, NULL, 0, 0))

{

     //使用非模式对话框时候,需要添加该消息处理过程

       if ((hDisplayDlg == 0) || (!IsDialogMessage (hDisplayDlg, &msg)))

      {

         TranslateMessage(&msg);

         DispatchMessage(&msg);

      }

        

}

差不多了,下面准备学习底层的一些东西,希望能坚持下来。本人菜鸟,有什么问题和建议大家可以联系:

luocan1358@126.com。或者群里的兄弟,可以直接QQ我。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值