• 10216阅读
  • 5回复

[讨论]Qt中如何在frameless和Translucent的widget中加入WS_THICKFRAME [复制链接]

上一主题 下一主题
离线lingdhox
 

只看楼主 正序阅读 楼主  发表于: 2014-05-09
Qt在windows上使用updatelayeredwindow需要同时设置FramelessWindowHint 和WA_TranslucentBackground
但是这样会导致窗口属性没有WS_THICKFRAME和WS_CAPTION
WS_THICKFRAME 影响窗口自动最大化(拖动到边缘)
WS_CAPTION 影响最小化动画
还有就是无边框时, 坐标都变成了客户区坐标

实际上, 在vc/mfc中使用updatelayeredwindow时, 是可以保留caption 和thickframe, (参考迅雷和qq的聊天界面)
而Qt实现的软件中yy也是可以的. (我用spy抓了yy视频窗口的属性).
但是我不知道怎么实现的.
在winidchange事件中用SetWindowLong强制加入WS_THICKFRAME
会导致莫名其妙的问题(最大化时, 无法刷新, 不会重绘).
希望大神指点一下
离线lingdhox

只看该作者 5楼 发表于: 2014-05-12
回 roywillow 的帖子
roywillow:
你试试直接用win32 api创建一个窗口试试?如果这个能办到的话那就是qt自己的问题了

这个我试过了. 原生的win32窗口是没有问题的
我也跟了qt的源码, Qt在updatelayeredwindow时, 一定要Frameless, 所以就没法解决了.
不知道yy的界面是如何解决的

这是我的测试代码, 麻烦看看
  1. test2.h
  2. #include <QWidget>
  3. class test2 : public QWidget
  4. {
  5. Q_OBJECT
  6. public:
  7. test2(QWidget *parent);
  8. ~test2();
  9. public slots:
  10.   void OnBtnClicked();
  11. protected:
  12. bool nativeEvent( const QByteArray & eventType, void * message, long * result );
  13. void paintEvent(QPaintEvent*);
  14. bool event(QEvent * event);
  15. // wm msg handler
  16. bool HandleGetMinMaxInfoMsg(MSG *msg, long *result);  
  17. private:
  18. };
  1. test2.cpp
  2. #include "test2.h"
  3. #include <Windows.h>
  4. #include <QEvent>
  5. #include <QDebug>
  6. #include <QDesktopWidget>
  7. #include <windowsx.h>
  8. #include <QWindow>
  9. #include <QSurfaceFormat>
  10. #include <QPushButton>
  11. #include <QPainter>
  12. #include <QApplication>
  13. test2::test2(QWidget *parent)
  14. : QWidget(parent)
  15. {
  16. QPushButton *pbn = new QPushButton("test", this);
  17. pbn->move(100, 100);
  18. connect(pbn, SIGNAL(clicked()), this, SLOT(OnBtnClicked()));
  19. setWindowFlags(Qt::FramelessWindowHint | Qt::Window );
  20. setAttribute(Qt::WA_TranslucentBackground);
  21. }
  22. test2::~test2()
  23. {
  24. }
  25. bool test2::event(QEvent * e)
  26. {
  27. if(e->type() == QEvent::WinIdChange)
  28. {
  29.   HWND hWnd = (HWND)this->winId();
  30.   LONG lStyle = ::GetWindowLong(hWnd, GWL_STYLE);
  31.   ::SetWindowLong(hWnd, GWL_STYLE, lStyle  | WS_OVERLAPPED | WS_THICKFRAME);
  32. }
  33. return QWidget::event(e);
  34. }
  35. bool test2::nativeEvent( const QByteArray & eventType, void * message, long * result )
  36. {
  37. MSG *msg = (MSG *)message;
  38. const int captionHeight = 32;
  39. const int frameWidth = 5;
  40. switch (msg->message )
  41. {
  42. case WM_GETMINMAXINFO :
  43.   HandleGetMinMaxInfoMsg(msg, result);
  44.   *result = 0;
  45.   return true;
  46. }
  47. return QWidget::nativeEvent(eventType, message, result);
  48. }
  49. void test2::paintEvent( QPaintEvent* )
  50. {
  51. QPainter painter(this);
  52. HWND hWnd = (HWND)this->winId();
  53. RECT winRect;
  54. ::GetWindowRect(hWnd, &winRect);
  55. QRect qWinRect = QRect(0, 0, winRect.right - winRect.left, winRect.bottom - winRect.top);  
  56. QRect rc = rect();
  57. qDebug () << "paintevent" << rc  << qWinRect;
  58. painter.fillRect(rc, QColor(0,0,0));
  59. rc.adjust(6, 30, -6, -6);
  60. painter.fillRect(rc, QColor(0, 0, 255, 250));
  61. }
  62. bool test2::HandleGetMinMaxInfoMsg( MSG *msg, long *result )
  63. {
  64. QRect maxRect = QApplication::desktop()->availableGeometry();
  65. QSize szMin = this->minimumSize();
  66. QSize szMax = this->maximumSize();
  67. PMINMAXINFO lpMMI = (PMINMAXINFO)msg->lParam;
  68. lpMMI->ptMaxSize.x = maxRect.width();  
  69. lpMMI->ptMaxSize.y = maxRect.height();
  70. lpMMI->ptMaxPosition.x = 0;
  71. lpMMI->ptMaxPosition.y = 0;
  72. lpMMI->ptMinTrackSize.x = szMin.width();
  73. lpMMI->ptMinTrackSize.y = szMin.height();
  74. lpMMI->ptMaxTrackSize.x = szMax.width();
  75. lpMMI->ptMaxTrackSize.y = szMax.height();
  76. return true;  
  77. }
  78. void test2::OnBtnClicked()
  79. {
  80. static bool bMin = false;
  81. bMin = !bMin;
  82. if(bMin)
  83. {
  84.   showMaximized();
  85. }
  86. else
  87. {
  88.   showNormal();
  89. }
  90. }



离线lingdhox

只看该作者 4楼 发表于: 2014-05-12
回 roywillow 的帖子
roywillow:你试试直接用win32 api创建一个窗口试试?如果这个能办到的话那就是qt自己的问题了 (2014-05-11 09:16) 

这个我试过了. 原生的win32窗口是没有问题的
我也跟了qt的源码, Qt在updatelayeredwindow时, 一定要Frameless, 所以就没法解决了.
不知道yy的界面是如何解决的
离线roywillow

只看该作者 3楼 发表于: 2014-05-11
回 lingdhox 的帖子
lingdhox:有可能的, 看yy就知道.
就是不知道是怎么做到的.
因为Qt在调用updatelayeredwindow时, 会判断frameless和alpha透明的 (2014-05-10 10:08) 

你试试直接用win32 api创建一个窗口试试?如果这个能办到的话那就是qt自己的问题了
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线lingdhox

只看该作者 2楼 发表于: 2014-05-10
回 roywillow 的帖子
roywillow:你是想绘制异形窗体并且还能有窗口边框……?
我怎么一直记得是不可能的来着…… (2014-05-10 10:01) 

有可能的, 看yy就知道.
就是不知道是怎么做到的.
因为Qt在调用updatelayeredwindow时, 会判断frameless和alpha透明的
离线roywillow

只看该作者 1楼 发表于: 2014-05-10
你是想绘制异形窗体并且还能有窗口边框……?
我怎么一直记得是不可能的来着……
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
快速回复
限100 字节
 
上一个 下一个