LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: rambo0808

MiniGUI什么语句可获取主窗口句柄,等同于VC中AfxGetApp()->GetMainWnd();

[复制链接]
发表于 2007-4-28 18:00:13 | 显示全部楼层
进行绘制操作为什么不在 MSG_PAINT 的时候?
我还是第一次看到有在 MSG_PAINT 之外的地方用 BeginPaint()/EndPaint()。
(其他地方可以用GetClientDC()/GetDC()来获取DC,后面别忘了ReleaseDC())

另外,其他时候想重绘窗口可以调用UpdateWindow()。(产生一个MSG_PAINT)
(移动/显示窗口的时候、调用InvalidateRect的时候、调用UpdateWindow的时候 都会产生MSG_PAINT)



你想测试的话,先把无关的代码都去掉。看下仅仅生成一个框架可不可行?z

如果实在不行的话,自己CreateWindow手工创建那些控件算了。。。
(何必躲那个懒呢?有这些时间自己都写一大堆控件出来了)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-28 20:49:26 | 显示全部楼层
1、之所以不在MSG-PAINT 中重绘,是因为在MSG—PAINT中重绘时会出现刷屏现象,客户区域出现严重的闪烁现象,然而在MSG_ERASEBKGND中重绘却不会出现这个现象。

2、对的,可以用CreateWindow来创建那些控件,然后把定时器放到主窗口中,当点击创建的按钮控件时候,需要把这个点击的消息发到主窗口,但主窗口要怎样才能接受到这个消息?这点是我想不明白的。
    不知道,在MSG_CREATE 中用CreateWindow()直接创建控件,然后在MSG_COMMAND中用 case ID_OK 能否接受到消息,我试试看
回复 支持 反对

使用道具 举报

发表于 2007-4-28 23:56:01 | 显示全部楼层
重绘最好用双缓冲方法来进行,这是避免刷屏的常用方法
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-29 02:27:12 | 显示全部楼层
1, 在控件窗口试了一下,GetParent(hDlg)为hMainWnd,
GetMainWindowHandle(hDlg)为hDlg,

所以用GetParent(hDlg)放在PostMessage()中不能返回,问题就象你说的那样,DialogBoxIndirectParam()不托管窗口了

2,

  1.     switch (message) {

  2.         case MSG_CREATE:


  3.           hwnd = CreateWindow (CTRL_BUTTON,
  4.                         "This is a buttom",
  5.                         WS_CHILD | WS_VISIBLE | SS_LEFT,
  6.                         IDC_BUTTON,
  7.                         10, 10, 380, 100, hWnd, 0);
  8.             InitDialogBox(hWnd);
  9.             return 0;


复制代码

这样来创建按钮的话,最后用 IDC_BUTTON 来用这个按钮,但是这样创建的按钮好象不能按下。是风格设置的问题么。
回复 支持 反对

使用道具 举报

发表于 2007-4-29 11:50:22 | 显示全部楼层
你创建的是个 Button 怎么用 SS_LEFT 风格?用 BS_PUSHBUTTON 看看。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-30 02:11:53 | 显示全部楼层
用CreateWindow 来创建控键的效果很不错

前面提到刷屏的问题,用在MSG-ERASEBKGND中重绘的办法可以解决。

前面  DoDo  说到用双缓存来解决,我看了一下资料,资料上面介绍这个方法分下面几步,

  1. 1)、为屏幕 DC 创建兼容的内存 DC: CreateCompatibleDC()

  2. if(!m_dcMemory.CreateCompatibleDC(NULL)) // CDC m_dcMemory;
  3. {
  4.   ::PostQuitMessage(0);
  5. }
  6. 2)、创建位图:CreateCompatibleBitmap()

  7. m_Bmp.CreateCompatibleBitmap(&m_dcMemory, rt.Width(), rt.Height()); // CBitmap m_Bmp;

  8. 3)、把位图选入设备环境:SelectObject(),

  9. 可以理解为选择画布
  10. ::SelectObject(m_dcMemory.GetSafeHdc(), m_Bmp);

  11. 4)、把绘制好的图形“拷贝“到屏幕上:BitBlt()
  12. pdcView->BitBlt(0, 0, rt.Width(), rt.Height(), &m_dcMemory, 0, 0, SRCCOPY);
复制代码


   这个是在VC++下实现的,在MINIGUI 中提供了第一步的函数 CreateCompatibleDC(),但m_dcMemory 在GUI下也可以自己定义吗?

  GUI没有其他几步定义的API,不知道是否可以这样,
第二步改为这样 ,定义一个BITMAP句柄 bmp1(怎么能让他定义在内存中?),然后把一个 1.bmp 位图直接赋给他. 
第三,四 步等效为
       LoadBitmapFromFile(HDC_SCREEN, &s_bmp, bmpno);
           hdc = BeginPaint (hWnd);
           FillBoxWithBitmap (hdc, 0, 0, 512, 480, &s_bmp);
回复 支持 反对

使用道具 举报

发表于 2007-4-30 09:46:45 | 显示全部楼层
  1. hdcMem = CreateCompatibleDC (HDC_SCREEN);
  2. LoadBitmapFromFile (HDC_SCREEN, &s_bmp, bmpno);
  3. FillBoxWithBitmap (hdcMem, 0, 0, 512, 480, &s_bmp);
  4. UnloadBitmap (&s_bmp);
  5. hdc = BeginPaint (hWnd);
  6. BitBlt (hdcMem, 0, 0, 512, 480, hdc, 0, 0, 0);
  7. DeleteCompatibleDC (hdcMem);
  8. ...
  9. EndPaint (hWnd, hdc);
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-5-1 00:30:13 | 显示全部楼层
创建的代码

  1.          case MSG_PAINT:
  2.                      hdcMem = CreateCompatibleDC (HDC_SCREEN);
  3.                      LoadBitmapFromFile (HDC_SCREEN, &s_bmp, bmpno);

  4.               //    LoadBitmapFromFile (hdcMem, &s_bmp, bmpno);  出现刷屏

  5.        FillBoxWithBitmap (hdcMem, 0, 0, 512, 480, &s_bmp);
  6.                      UnloadBitmap (&s_bmp);
  7.                     
  8.                      hdc = BeginPaint (hWnd);
  9.                      BitBlt (hdcMem, 0, 0, 512, 480, hdc, 0, 0, 0);
  10.                      DeleteCompatibleDC (hdcMem);

  11.                   if(bmpno[0] == '3' && bmpno[1] == '1')
  12.                      {
  13.                      bmpno[0] = '0';
  14.                      bmpno[1] = '0';
  15.                      }
  16.             
  17.                  if(bmpno[1] == '9')

  18.                     {  
  19.                       bmpno[0] = bmpno[0]+1;
  20.                       bmpno[1] = '0';
  21.                     }
  22.                 else
  23.                     {bmpno[1] = bmpno[1]+1;}

  24.                 EndPaint (hWnd, hdc);
复制代码

代码实验的结果还是出现刷屏现象,其程度和直接使用MSG_PAINT重绘的刷屏程度一样。
他们都是第一个显示循环刷屏现象最为严重,第二个循环稍微好一点,后面的循环程度较轻,每个循环有几次的刷屏。
回复 支持 反对

使用道具 举报

发表于 2007-5-1 10:39:36 | 显示全部楼层
试试这样呢?(BeginPaint获得的DC是带区域性的是那些“需要绘制的区域”)
  1. hdc = BeginPaint (hWnd);
  2. hdcMem = CreateCompatibleDC(hdc);
  3. ...
复制代码

但是对于HDC_SCREEN又有:
from: <MiniGUI Prog. Guide>
MiniGUI 在启动之后,就建立了一个全局的屏幕设备上下文(HDC_SCREEN)。该 DC 是针对整个屏幕的,
并且没有任何预先定义的剪切域。在某些应用程序中,可以直接使用该设备上下文进行绘图,将大大提高绘图效率。

不过对于消除刷屏现象CreateCompatibleDC()是肯定的:
from: <MiniGUI Prog. Guide>
利用内存设备上下文,可以在系统内存中建立一个类似显示内存的区域,然后在该区域中进行绘图操作,
结束后再复制到显示内存中。这种绘图方法有许多好处,比如速度很快,减少直接操作显存造成的闪烁现象等。


另外,MiniGUI里面还有个HDC CreateMemDCFromBitmap(HDC, BITMAP*) 函数,不过这个函数的效率可能不高:
from: <MiniGUI Prog. Guide>
需要注意的是,从 BITMAP 对象创建的内存 DC 直接使用 BITMAP 对象中的 bmBits
所指向的内存,该内存存在于系统内存,而不是显示内存中。
...
许多 GAL 引擎不能对系统内存到显示内存的 BitBlt 操作提供硬件加速,所以,FillBoxWithBitmap 函数,
以及从 BITMAP 对象或者 MYBITMAP 对象创建的内存 DC 无法通过硬件加速功能快速 BitBlt
到其他 DC 上。如果希望达到这样的效果,可以通过预先创建的建立于显示内存中的 DC 进行快速的 BitBlt 运算。


综合上面几点,可以试试这样:
  1. hdc = BeginPaint (hWnd);
  2. hdcMem = CreateCompatibleDC(hdc);
  3. LoadBitmapFromFile (hdcMem, &s_bmp, bmpno);        // 之前那个刷屏可能是Create自HDC_SCREEN,变成直接从文件装载到显存这样肯定有刷屏现象了。
  4. FillBoxWithBitmap
  5. ...
  6. 或者这样:
  7. hdc = BeginPaint (hWnd);
  8. LoadBitmapFromFile (hdc, &s_bmp, bmpno);
  9. hdcMem = CreateMemDCFromBitmap (hdc, &s_bmp);
  10. UnloadBitmap
  11. ...
复制代码



当然,以上都是我个人的纸上谈兵。我并没有搞过MiniGUI,这种东西还是需要自己多实践才知道的——也许你开始那种方法是正确的。

还有,记得以前Windows中避免刷屏有两个方面
1。就是双缓冲
2。是避免系统刷背景(ERASEBKGND的时候返回 TRUE)——类似于你开始那样。
回复 支持 反对

使用道具 举报

发表于 2007-5-1 10:58:51 | 显示全部楼层
这里补充一点 双缓冲 的意义:
直接对显存的操作无疑是高效的,但是当对显存操作的同时进行了比较耗时的操作(比如:磁盘文件I/O、大量耗时的计算 等),这样的绘制过程就会造成图像闪烁的现象。
这样还不如先暂时保留当前显存的内容不变,在内存中开辟一块和显存一样的空间,而对这块空间进行这种耗时的操作,等所有操作做完后再把这整块内存copy到显存空间中去。这样就有效的避免了那种耗时操作所造成的闪烁现象。


而,ERASEBKGND的那种方法:
默认的系统会自动的对背景进行绘制操作,就是说每当你绘制完前景后系统会自动绘制一次背景这样频繁的绘制动作无疑是造成闪烁的一个因素。而通过手工接管ERASEBKGND消息就禁止了系统的自动绘制操作,从而避免了那样频繁的绘制动作。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表