多功能输入法(5)

来源:互联网 发布:黄俊郎和方文山知乎 编辑:程序博客网 时间:2024/04/27 23:33

4 前端界面模块实现

 

 

4.1 窗口的创建

 

4.1.1 创建一个窗口的过程

输入法的前端界面里面,包括状态窗口,编码输入窗口与候选窗口三个主要的窗口。这些窗口都需要通过Windows程序的API所提供我们一系列的函数创建。创建一个窗口的过程如下:

1.    初始化WinMain 函数

2.定义和注册窗口类

3.利用CreateWindow函数创建一个窗口

4.创建窗口函数后,调用ShowWindow 函数显示窗口,以及使用UpdateWindow函数更新窗口。

    5.窗口进入消息循环

综述, 一个窗口的创建需要经过初始化WinMain入口函数 ,定义注册窗口类,

创建窗口,显示和更新窗口,最后到消息循环这一个过程。

  

 

4.2 窗口贴图

 

4.2.1 为什么要进行窗口贴图

输入法至今都有好一段的历史,在这段时间里面。输入法无论在外观和功能上都发生了巨大的改变。特别在用户界面上,增加很多的设计元素在内,窗口的外观上有了质的飞跃。话说回来,看到标题也许会问:“同学你在说什么呢?说那么一堆无用的话”。其实要讲的是关于一些外观上的事情,联想到Windows为什么能够取得那么多用户的青睐,很大程度是在于它美化的图形外观,以及方便简单的操作。话说到这里,我引出的事情是就是关于输入法窗口的贴图。什么是窗口贴图?它的意义所在呢?

所谓的窗口贴图就是在程序所创建的窗口基础上,进行外观上的改造,美化等操作。它的意义其中有:

第一,图形用户界面能够为用户提供界面友好的操作环境。

第二,图形用户界面能够吸引用户的注意力和关注。

第三,图形用户界面能为软件增添内涵。

以上是从功能上,外观上,价值上讲述用户界面的作用。就是因为这些作用,我们有理由相信为了让用户得到更好的体现,美化窗口是必要的而且是根据历史的发展经验告诉我们的,丰富程序的用户界能为用户带来更多,更好的体现。

 

4.2.2 窗口贴图的原理

在进行贴图之前,我们需要需要了解DDB位图和DIB位图之前的相关的事情。使用位图资源时候,调用LoadBitmap函数将位图资源调入内存,此函数忽略了调色板和其他信息,使用系统调色板显示位图,这就是设备相关的位图,即DDB位图。如果保留位图的颜色表信息,颜色表描述了像素点值是如何与RGB值相对应的。这个颜色表不一定与特定的图形输出设备兼容,因此位图就称与设备无关的位图,即DIB格式位图。LoadBitmap函数具有将DIB位图转换DDB位图的功能,但只是对以资源形式存放的位图有此功能,对任意存放在磁盘上的位图,可以使用其他的相关的函数进行转换。

DDB依赖于具体设备的,DDB的颜色模式必须与输出设备相一致。例如当前的显示设备是256色模式,那么DDB必然也是256色的。DDB依依赖输出设备,所以DDB只能存在于内存中。DIB与设备无关性,在于它的颜色模式与设备无关。例如一个256色的DIB可以在真彩色显示模式下使用,同样也可以在16色模式下使用。256色以下,包括256色的DIB拥有自己的颜色表,像素独立于系统调色板,它可以永久存放在磁盘中。

根据以上的DDBDIB上的区别,我们很容易知道其原理所在。当我们把已经制作好的256色的BMP位图导入Visual c++ 里面作为一种系统资源使用,保存在磁盘上,当程序需要这个位图的时候,那么就将其DIB位图转换DDB位图,然后通过相关使用DDB位图的函数显示到指定的窗口。

 

                4-1 DIBDDB图示

4.2.3 窗口贴图的过程

      窗口贴图大概一个过程如下图: 

    

4-1  图为窗口贴图流程图

接下来的工作就是要了解这样的一个贴图代码实现过程,大概有一个感性认识的过程。在窗口中显示图像时的过程:

一、首先是获取设备环境中的句柄。

二、获取与设备环境兼容的内存设备描述表,将要显示位图的句柄选入内存设备描述表,即先将位图显示在内存中。

三、将内存设备描述表中的位图通过BitBlt函数显示在窗口屏幕中。

四、删除内存设备环境,释放资源

当应用程序运行时需要调用到的资源才被装入到内存里面,当不需要调入到内存里面,资源仍然保留在磁盘上。

 

4.2.4 窗口贴图知识点

1.位图资源

在进行贴图之前,我们还是有必要先了解一下有关于位图资源的知识。位图(BITMAP)是由点阵数据表示的图像。位图在Windows中 主要有两个用途:一、在屏幕上显示图像。在Windows系统中包含了很多的位图,有滚动条的箭头,系统菜单框、各种按钮等。也可以在屏幕上显示画笔创建的图像。二、创建刷子。刷子是Windows用来填充显示的像素图案。

打开Visual C++ 菜单 Insert-àResource 选择Bitmap,使用New命令进行创建位图资源。

 

          4-1 位图资源对话框

建立后,我们从外部加载一张256色或者少与256色的BMP位图,进行贴图。

位图资源的内存选项是可移动的,但是却是不可丢弃的。同时位图是GDI对象,在程序之间不可共享,并且当程序结束时,不能从内存自动删除。当程序结束时,使用DeleteObject函数可以将位图和刷子从内存中删除。

 使用LoadBitmap函数获取位图的句柄,LoadBitmap函数的一般形式如下:

 HBITMAP     loadBitmap(hinst,lpszBitmap)

HINSTANCE    hinst  // 实例句柄

LPCSTR     lpszBitmap//位图的名称

此函数将位图资源装入内存。

DeleteOject函数的一般形式如下:

BOOL  DeleteOject(hgdiobj)

HGDIOBJ hgdiobj// 要删除的对象的句柄

此函数从内存中删除对象,并释放所占存储空间。

 

2.内存设备描述表:

    了解了位图资源后,我们可以利用LoadBitmap 函数获取我们所需的位图句柄,但我们发现只是获取位图句柄还不能完成我们贴图的工作。因此,我们还要了解内存设备描述表相关的知识,内存描述表是一个重要结构体,封装windows一些重要数据。我们可以比喻内存设备描述表为一个衣柜,把位图比喻为一件衣服,衣柜被划分很多格,每一个格当中只是摆放一件衣服,衣服就摆放在衣柜里面。然而衣柜能够很好管理衣服,但是没有打开衣柜之前,衣服是不可以显示的。也就是说,内存设备描述表类似一个管理位图的一个衣柜,但这个衣柜仍然是没有打开之前是不可见里面的。

 

3.显示DDB位图:

    当位图被加载到内存后,我们并不能在我们创建的窗口显示出其位图到屏幕上。那么,为了可以将内存里的位图显示到屏幕上去,我们可以使用BitBit函数它的一般形式如下:

  BOOL BitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop);

 

HDC  hdcDest; // 目的设备表描述句柄

int nXDest;// 目的矩形左上角的x坐标

int nYDest;// 目的矩形左上角的y坐标

int nWidth;// 位图的宽度

int nHeight;//位图的高度

HDC hdcSrc;//源设备描述表句柄

int nXSrc;//源位图的左上角的x坐标

int nYSrc;//源位图的左上角的y坐标

DWORD dwRop;//拷贝时的像素操作

通过这个函数,内存的位图就能够显示到屏幕当中。可以根据需要进行选取自己所需要的区域组合成自己想要的图像。

4.2.5 实现皮肤变换

    为了实现输入法在外观上的变换,实现皮肤的变换,为了实现这样一个功能,需要对其进行定义一个函数来对其进行皮肤的变换。

 

大概的思路:

    创建一个LoadSkin这个自定义函数,让它回返一个HBITMAP句柄的值。其次要利用LoadImage函数加载外部的图片,第三利用DrawState 显示加载的图片。

 

实现过程如下:  

//加载外部图片,进行皮肤贴图,

HBITMAP LoadSkin(HWND hWnd,LPTSTR SkinName)

{

    HDC hDc;

    HBITMAP hBitmap ;

    hDc=GetDC(hWnd);//获取设备环境DC

    hBitmap=(HBITMAP)LoadImage(hInst,SkinName,IMAGE_BITMAP,0,0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE |LR_LOADFROMFILE );

    DrawState(hDc,NULL,NULL,(LPARAM)hBitmap,0,0,0,0,0,DST_BITMAP);

    return hBitmap;

}

 

函数说明:

函数原型:HANDLE LoadImage

NINSTANCE hinst//指向要装载的图像所在的模块实例

LPCTSTR lpszName//指向图像的文件名或其ID

UINT uType//指定其图像类型,包括位图,光标,图标

int cxDesired//指定图标或者光标的宽度

int CyDesired// 指定图标或者光标的高度

UINT fuLoad);//Load flags

 

BOOL DrawState(

  HDC hdc,                     // handle to device context

  HBRUSH hbr,                  // handle to brush

  DRAWSTATEPROC lpOutputFunc,  // callback function

  LPARAM lData,                // image information

  WPARAM wData,                // more image information

  int x,                       // horizontal location

  int y,                       // vertical location

  int cx,                      // image width

  int cy,                      // image height

  UINT fuFlags                 // image type and state

);

在实现的过程种,我们只要调用其LoadSkin函数,就要实现简单变换效果。

例如:

 

static HBITMAP g_hBitmap;//全局换皮肤

Switch(message)    

{

case WM_CREATE:

    g_hBitmap=LoadSkin(hWnd,"input.bmp");

      break;

……………………

…………………….

省略

……………………

}

这个过程,我们只需要指定要变换的窗口的句柄,以及外部被加载的图片名称

这样就可以实现一个简单的变换皮肤功能。

 

 

原创粉丝点击