技术开发 频道

WindowMobile上的模拟LED显示屏插件

  这个函数的作用是:根据指定的字符串,生成 LedBitmap;并返回 LedWidth (该图片的LED屏幕坐标的像素宽度);在这个函数里,临时位图实际上在使用完毕后清除,但我为了在PC上的范例的对话框上展示它,所以没有立即清除。

  如下图所示,为 4 个 LED 的放大图形,上面两个为熄灭,下面两个为点亮状态;

  【注意】我们绘制的原始图像特点是“白底黑字”,因此黑色映射到LED图像的“点亮”状态,白色映射到“熄灭”状态;在下面代码中可看到这一点;

  下面是 CreateLedBitmap 的代码,在这段代码中,包含了前面所讲的对“像素定位”的非常重要的方法和信息,涉及了扫描行宽度,位图中的逆序扫描,在图像数据中的像素定位,在像素中的RGB通道定位,这些都是通过指针来完成的,需要务必小心以确保指针的指向合法和正确。

  //根据指定的字符串创建实际的用于滚动的位图(比实际图像会增大4倍)

  //返回创建的位图的未LED化像素长度(也就是实际字符串的绘制长度)

  int CreateLedBitmap(HWND hWnd, TCHAR* text)

  {

  //创建字体

  LOGFONT lf;

  HFONT hFont = NULL, hOldFont = NULL;

  SIZE size = {0,0};

  BITMAPINFO bminfo;

  HBITMAP hOldBitmap; //临时位图(为非LED化的实际像素大小)

  HBRUSH hBrush =NULL;

  RECT rc;

  int i, j, stride, strideTemp;

  //两个位图的像素数据地址

  BYTE *lpBytes, *lpBytesTemp, *lpLed;

  //设置位图信息

  memset(&bminfo.bmiHeader, 0, sizeof(BITMAPINFOHEADER));

  bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); //40

  bminfo.bmiHeader.biPlanes = 1;

  bminfo.bmiHeader.biBitCount = 24;

  //测量字符串的大小,其决定作用的还有当前HDC中的字体

  HDC hWndDC = GetDC(hWnd);

  HDC hDC = CreateCompatibleDC(hWndDC);

  ReleaseDC(hWnd, hWndDC);

  HFONT hSysFont = (HFONT)GetStockObject(DEVICE_DEFAULT_FONT);

  GetObject(hSysFont, sizeof(LOGFONT), &lf);

  lf.lfWeight = FW_NORMAL;

  lf.lfHeight = (long) -((11.0 * (double)GetDeviceCaps(hDC, LOGPIXELSY) / 72.0) + .5);

  //lf.lfHeight = 11;

  wcscpy(lf.lfFaceName, _T("宋体"));

  // create the font

  hFont = CreateFontIndirect(&lf);

  //创建背景刷

  hBrush = CreateSolidBrush(BKCOLOR_LED);

  hOldFont = (HFONT)SelectObject(hDC, hFont);

  //测量字符串,得到的高度应该是14,宽度取决于字符串

  GetTextExtentPoint32(hDC, text, wcslen(text), &size);

  //计算扫描行宽度

  stride = (24 * size.cx * LEDSIZE + 31)/32 * 4;

  strideTemp = (24* size.cx + 31)/32 * 4;

  bminfo.bmiHeader.biWidth = size.cx * LEDSIZE;

  //去掉上下的2行像素

  bminfo.bmiHeader.biHeight = size.cy * LEDSIZE; //(14-2)*4=48pixels,

  bminfo.bmiHeader.biSizeImage = bminfo.bmiHeader.biHeight * stride;

  //创建位图

  if(g_BitmapLed != NULL)

  DeleteObject(g_BitmapLed);

  if(g_BitmapTemp != NULL)

  DeleteObject(g_BitmapTemp);

  //注意WinCe平台上不支持内存映射,所以无法提供我们自己的位图数据,而是由系统负责分配

  g_BitmapLed = CreateDIBSection(hDC, &bminfo, DIB_RGB_COLORS, (VOID**)&lpBytes, NULL, 0);

  //是否创建成功?

  if(g_BitmapLed == NULL)

  {

  goto CLEARNUP_EXIT;

  }

  //创建实际大小的位图

  bminfo.bmiHeader.biWidth = size.cx;

  bminfo.bmiHeader.biHeight = size.cy;

  g_BitmapTemp = CreateDIBSection(hDC, &bminfo, DIB_RGB_COLORS, (VOID**)&lpBytesTemp, NULL, 0);

  if(g_BitmapTemp == NULL)

  {

  goto CLEARNUP_EXIT;

  }

  //在实际绘图上进行绘制

  hOldBitmap = (HBITMAP)SelectObject(hDC, g_BitmapTemp);

  rc.left = rc.top = 0;

  rc.right = size.cx;

  rc.bottom = size.cy;

  //填充白色背景

  FillRect(hDC, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH));

  SetTextColor(hDC, RGB(0,0,0)); //黑色字体

  SetBkMode(hDC, TRANSPARENT);

  //绘制字符串

  DrawText(hDC, text, wcslen(text), &rc, DT_LEFT | DT_VCENTER| DT_NOCLIP | DT_SINGLELINE);

  //现在再把LED图选入DC中去刷一次背景

  SelectObject(hDC, g_BitmapLed);

  //rc设置为LED图的大小

  rc.right = size.cx * LEDSIZE;

  rc.bottom = size.cy * LEDSIZE;

  FillRect(hDC, &rc,hBrush);

  //复原DC

  SelectObject(hDC, hOldBitmap);

  SelectObject(hDC, hOldFont);

  //现在根据它进行拷贝到新的位图中,去掉了上下两行像素,i,j是在 bitmaptemp中的坐标

  //每个LED灯实际上是 4 * 4像素的小矩形块!设置6个像素即可

  for(j = 0; j< size.cy; j++)

  {

  for(i = 0; i < size.cx; i++)

  {

  //把指针定位到LED灯的左上角!

  //注意这里行是倒序的!(所以距离内存起始点的最远的哪一行才是LED第一行,逐行向内存起始处返回)

  lpLed = lpBytes + stride*(j*LEDSIZE+3) + i*3*LEDSIZE;

  if(lpBytesTemp[strideTemp * j + i*3] == 0) //即,该通道为黑色,表示这里是字迹(应该点亮这个灯)

  {

  //点亮 9 * 9

  //第一行 0-Blue, 1-Green, 2-Red

  lpLed[0]= 76, lpLed[1]=154, lpLed[2]=186;

  lpLed[3]=130, lpLed[4]=207, lpLed[5]=236;

  lpLed[6]= 56, lpLed[7]=145, lpLed[8]=204;

  //第二行

  lpLed -= stride;

  lpLed[0]=127, lpLed[1]=214, lpLed[2]=245;

  lpLed[3]=193, lpLed[4]=232, lpLed[5]=247;

  lpLed[6]= 43, lpLed[7]=167, lpLed[8]=241;

  //第三行

  lpLed -= stride;

  lpLed[0]= 56, lpLed[1]=144, lpLed[2]=204;

  lpLed[3]= 43, lpLed[4]=160, lpLed[5]=231;

  lpLed[6]= 43, lpLed[7]=125, lpLed[8]=207;

  }

  else

  {

  //熄灭 9 * 9

  //第一行 0-Blue, 1-Green, 2-Red

  lpLed[0]= 65, lpLed[1]= 65, lpLed[2]= 65;

  lpLed[3]= 84, lpLed[4]= 84, lpLed[5]= 84;

  lpLed[6]= 65, lpLed[7]= 65, lpLed[8]= 65;

  //第二行

  lpLed -= stride;

  lpLed[0]= 84, lpLed[1]= 84, lpLed[2]= 84;

  lpLed[3]= 66, lpLed[4]= 66, lpLed[5]= 66;

  //lpLed[6]= 65, lpLed[7]= 65, lpLed[8]= 65;

  //第三行

  lpLed -= stride;

  lpLed[0]= 65, lpLed[1]= 65, lpLed[2]= 65;

  //lpLed[3]=130, lpLed[4]=207, lpLed[5]=236;

  //lpLed[6]= 56, lpLed[7]=145, lpLed[8]=204;

  }

  }

  }

  CLEARNUP_EXIT:

  //清理

  if(hBrush !=NULL)

  DeleteObject(hBrush);

  if(hFont != NULL)

  DeleteObject(hFont);

  if(hDC != NULL)

  DeleteDC(hDC);

  return size.cx;

  }

0
相关文章