嘿,我来帮您!
53.1℃
  • duilib入门问题集
  • 技术文章
  • 2815

  • 2018-09-17 17:50:30

  • 原作者: 青岛江山信息技术有限公司

空间

问:如何把资源放入zip?
答: 先SetResourcePath设置资源目录,再SetResourceZip设置压缩资源文件名


问:如何设置窗体的初始化大小?
答:设置XML文件的Window标签的size属性。


问:如何设置鼠标可拖动窗体的范围大小?
答:设置XML文件的Window标签的caption属性。


问:如何设置窗体可以通过拖动边缘改变大小?
答:在窗体创建函数的第三个参数设置为UI_WNDSTYLE_FRAME才可响应拖动改变大小,和双击标题事件。


问:为何鼠标移动到边缘没有改变窗体大小的箭头出现,不能通过拖动改变窗体大小?
答:设置window标签的sizebox属性,例如sizebox="2,2,2,2"


问:窗体不可双击最大化如何实现?
答:在窗体创建函数的第三个参数设置为UI_WNDSTYLE_DIALOG。


问:应用程序exe图标如何设置?
答:使用窗体成员函数SetIcon,参数为资源icon的id。


问:初始化时,最大化窗体如何实现?
答:调用窗体的SendMessage给窗体发送最大化消息SC_MAXIMIZE,SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE,0);


问:动态改变窗体的大小如何实现?
答:使用窗体函数ResizeClient,参数分别重设的宽和高。


问:如何设置窗体屏幕居中显示?
答:使用窗体的CenterWindow函数。


问:窗体透明度如何设置?
答:设置window标签属性bktrans="true" alpha="200" alpha的值为0-255。这种设置是全体窗体透明度,所有控件都将变透明。
如果想单纯设置背景透明度控件不透明度,可以制作半透明的背景图片,设置window标签的bktrans="true",并且不设置alpha属性,切记!此时背景透明,其它控件不透明。
单独设置某个控件的透明度,可以使用图片的fade属性,或者mask属性。fade表示设置图片透明度,取值0-255。mask为设置透明的颜色。


问:默认设置的图片为拉伸平铺模式,如何设置不拉伸显示?
答:设置图片的source和dest属性,soure="左,上,右,下" dest="左,上,右,下"
表示将source区域的图片显示到按钮的dest区域上。这里的右和下是指坐标,不是指宽度和高度。右=左+width.下=top+height。


问:如何设置选定编辑框文字的背景颜色?

答:设置nativebkcolor属性。


问:如何设置按钮的鼠标悬浮时的字体颜色?
答:设置按钮的hottextcolor属性,相对的还有pushedtextcolor和focustextcolor.


问:如何设置按钮按下时字体的颜色?
答:设置按钮的pushedtextcolor属性,相对的还有hottextcolor和focustextcolor.



问:如何自定义xml控件?
答:自定义控件和复杂的控件类型都是由简单基本控件组成。
在写好一个自定义的控件xml模板后,
CDialogBuilder dlg_builder;
CControlUI * pControl = dlg_builder.Create("item.xml");
注意这里的item.xml要放在主界面的xml所在的文件夹内,并且无需在指定路径了。
该函数返回一个CControlUI的一个句柄,得到这样一个句柄就是一个控件了。
如果要获取复杂控件的某个子控件的句柄,然后想通过该句柄改变子控件的状态。
首先给这个子控件取一个名字,然后可以通过pControl的FindSubControl("name")来获取该
控件的句柄了。得到句柄后就可以设置它的所有属性了,例如
pbtn->SetAttribute(_T("normalimage"), _T("file='images\\downlist_ok.png' dest='20,14,32,26'"));就能更改它的状态图片了。


问:多线程下如何更改dui的界面信息?
答:线程里不要操作界面的信息,应该通过SendMessage或者PostMessage给界面的m_hWnd发送自定义消息。然后在界面的消息循环里面在做操作界面的动作。
自定义处理的消息处理函数可以从重写方法
LRESULT MyWnd::HandleCustomMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
//这里处理完后,bHandled置true 返回基类,让基类去操作
return WindowImplBase::HandleCustomMessage(uMsg, wParam, lParam, bHandled);
}
具体可以如下使用:
#define ON_PERCENT_MSG              WM_USER + 500
然后在线程函数中发送消息给界面
int DownloadView::on_percent( double percent, int index, INT_PTR user_data )
{
::SendMessage(m_hWnd, ON_PERCENT_MSG, (WPARAM)&percent, (LPARAM)user_data);
return 0;
}


最后在界面消息循环中进行处理消息
LRESULT DownloadView::HandleCustomMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
switch (uMsg)
{
case ON_PERCENT_MSG:
// 处理界面相关的操作
break;
default:
break;
}
return WindowImplBase::HandleCustomMessage(uMsg, wParam, lParam, bHandled);
}





问:如何让使用duilib的win32工程支持MFC?
答:
1、在stdafx.h加入以下
#define VC_EXTRALEAN
#include         // MFC 核心组件和标准组件
#include         // MFC 扩展
#include        // MFC 自动化类
#ifndef _AFX_NO_OLE_SUPPORT
#include // MFC 对 Internet Explorer 4 公共控件的支持
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include // MFC 对 Windows 公共控件的支持
#endif // _AFX_NO_AFXCMN_SUPPORT
2、在程序初始化main的开始加入mfc的初始化。
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
return 1;
}
3、设置页属性-->常规-->使用mfc设置为 Use MFC in a Shared DLL


4、设置C++-->代码生成-->运行时库根据debug或者release设置为MDD或者MD。


duilib绘图部分

图像的绘制大部分使用了绘制引擎的DrawImageString函数,该函数实现知道图像名称绘制到指定目标区域的功能
并且通过指定pStrModify的属性能够进行不同需求的绘制,例如,仅扣取源图像的某个位置绘制到目标的某个区域、
设置四边圆角绘制、为bmp等指定某种颜色为透明颜色、平铺或者拉伸绘制、设置透明度等。
DrawImageString最终又调用CRenderEngine::DrawImage进行绘制。

duilib中所有元素的显示都在整个消息循环的WM_PAINT中进行绘制。
第一次绘制之前会发送一个名为_T("windowinit")的通知。
然后为CControlUI的绘制,绘制的顺序为:背景颜色->背景图->状态图->文本->边框
会顺序调用CControlUI的以下函数。

  1. PaintBkColor(hDC); // 绘制背景颜色
  2. PaintBkImage(hDC); // 绘制背景图
  3. PaintStatusImage(hDC); // 绘制状态图
  4. PaintText(hDC); // 绘制文本
  5. PaintBorder(hDC); // 绘制边框

所以有需求在界面上动态绘制一些内容时,可以通过CControlUI进行子类化,然后重写PaintStatusImage,
在PaintStatusImage里面进行绘图操作。绘制时可以直接调用duilib绘制引擎进行绘制,比较便捷。当然也可以使用GDI+等库直接进行绘制。


duilib的图像文件的加载是通过一个开源库stb_image.c实现。
并只使用了该库的stbi_load_from_memory和stbi_image_free这两个功能函数。
该库的链接地址:http://nothings.org/stb_image.c
该库对图片的格式的支持情况说明如下:
JPEG 支持Baseline标准型的JPEG,不支持渐进式Progressive的JPEG
PNG   仅支持8位的png图像
BMP  不支持1bpp的bmp,不支持行程编码RLE的bmp
PSD  紧显示合成的图像,不支持额外的通道
GIF *comp always reports as 4-channel


所以在duilib中使用的图片时需要注意到这个限制,否则有些图片将显示不出来。


duilib中把图片文件加载到内存后,由库stb_image.c解析并最终转为DIB处理。
duilib支持从图片文件、从包含图片文件的压缩包文件和VC资源中载入图片。
载入后最终返回TImageInfo结构体指针,包含HBITMAP、图像宽度、图像高度、alpha通道、mask和资源类型等信息。
载入函数为:TImageInfo* CRenderEngine::LoadImage(STRINGorID bitmap, LPCTSTR type, DWORD mask);
duilib中所有的图片资源只从加载一次,然后保存在CPaintManagerUI中的m_mImageHash成员中,该成员为一个
hashmap存储TImageInfo*信息,当已经存在要绘制显示的图片信息时,直接从map中获取显示,否则从文件加载
在添加到map中。



问:如何管理duilib界面皮肤资源?
答:把所有XML文件在同一个目录下,图片资源另外放在一个地方。当如下进行布局资源时,skin目录为设置资源的目录,imagedir1目录放置1.xml文件利用到的图片资源,imagedir2放置2.xml文件利用到的资源。
然后1.xml文件文件中的图片资源名称需要加上相对于当前xml文件的路径信息即可。例如:normalimage="imagedir1/1.png"这样的形式。使用设计器为XML添加资源时会自动转化为相对路径。
skin/
1.xml
2.xml
imagedir1/
1.png
2.png
imagedir2/
1.png
2.png




需注意一个问题,那就是字体的管理。字体对于一个窗口来说是全局的,索引从0开始,font = 0表示使用排在第一位的字体。如果一个界面被拆分为多个XML文件管理,并且当每个单独的文件自己添加字体时,联合起来的时候,会跟其它的字体发生冲突,即索引不是原来的索引了。索引得从全局来看。按照全局的方式进行设置好索引后,对于每个xml文件的预览操作时,又看不到所见即所得的效果了。

微观空间

视觉上最易被忽视的元素空间。如果你是初学者,可能试图填满每一个空的空间。更有经验的设计师会鼓励你使用更多的空白。从用户的角度来看,很少有人会抱怨它有太多的空白。 缺少空间感会造成视觉干扰。相同的内容、元素的垂直位置。注意通过相同定位的元素创建的空间,创建的视觉层次、对比度和秩序感。涉及到图形设计这是至关重要的。通过内容可以易于阅读和扫描。

宏观空间

视觉上最易被忽视的元素空间。如果你是初学者,可能试图填满每一个空的空间。更有经验的设计师会鼓励你使用更多的空白。从用户的角度来看,很少有人会抱怨它有太多的空白。 缺少空间感会造成视觉干扰。相同的内容、元素的垂直位置。注意通过相同定位的元素创建的空间,创建的视觉层次、对比度和秩序感。涉及到图形设计这是至关重要的。通过内容可以易于阅读和扫描。