VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 1074|回复: 3

[讨论] static控件重绘问题

[复制链接]
50_avatar_middle
最佳答案
0 
在线会员 发表于 2019-10-9 18:12:36 | 显示全部楼层 |阅读模式
很有趣的现象:重绘static采取重设控件属性SS_OWNERDRAW实现的时候,特么的发现属性解释出现了差异,具体如下:

  1. SS_ENHMETAFILE | SS_LEFT == SS_OWNERDRAW | SS_RIGHT
复制代码


这就搞笑了,系统在解释属性的时候与预期不符:
spy去看了一下,系统是按照 SS_ENHMETAFILE | SS_LEFT 进行解释的,但我要的是右对齐呀 SS_RIGHT ???

spy 截图和代码如下:

spy截图

spy截图


  1. /*
  2. win32的static控件 SS_RIGHT(右对齐) 似乎有点问题
  3. */
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <commctrl.h>
  7. #include <stdio.h>
  8. #include <string.h>

  9. #pragma comment(lib,"user32.lib")
  10. #pragma comment(lib,"gdi32.lib")
  11. #pragma comment(lib,"kernel32.lib")
  12. #pragma comment(lib,"comctl32.lib")
  13. #pragma comment(lib,"shell32.lib")

  14. #define WM_STATICCUSTOMDRAW (UINT)(WM_USER+0x1001)
  15. HFONT setfont(HDC hdc,LPCTSTR font_name);
  16. int Static_draw(HWND hwnd,HDC hdc,RECT rect,UINT itemState);
  17. LRESULT CALLBACK StaticProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
  18. LRESULT CALLBACK ContainerProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);

  19. #define ID_STATIC_01 0x0001
  20. #define ID_STATIC_02 0x0002
  21. HINSTANCE GInstance;
  22. void regist_window(char* class_name,WNDPROC proc);
  23. void InitialWindow(HWND hwnd);
  24. LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);

  25. HFONT setfont(HDC hdc,LPCTSTR font_name)
  26. {
  27.     LOGFONT lf;
  28.     HFONT pre_font = (HFONT)GetCurrentObject(hdc,OBJ_FONT);
  29.     HFONT text_font;
  30.    
  31.     if(pre_font) {
  32.         GetObject(pre_font,sizeof(LOGFONT),&lf);
  33.         strcpy(lf.lfFaceName,font_name);
  34.         text_font = CreateFontIndirect(&lf);
  35.     }
  36.     pre_font = (HFONT)SelectObject(hdc,text_font);  
  37.    
  38.     return pre_font;
  39. }

  40. int Static_draw(HWND hwnd,HDC hdc,RECT rect,UINT itemState)
  41. {
  42.     char* text;
  43.     HFONT pre_font;
  44.     HBRUSH brush,pre_brush;
  45.     COLORREF color_text = RGB(255,255,255);
  46.     COLORREF color_bk = RGB(0,0,0);
  47.     int length;
  48.    
  49.     length = GetWindowTextLength(hwnd);
  50.     text = (char*)malloc(sizeof(char)*(length+1));
  51.     memset(text,0x00,length+1);
  52.     GetWindowText(hwnd,text,length+1);
  53.    
  54.     pre_font = setfont(hdc,"微软雅黑");
  55.     brush = CreateSolidBrush(color_bk);
  56.     pre_brush = (HBRUSH)SelectObject(hdc,brush);
  57.    
  58.     Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);
  59.     SetTextColor(hdc,color_text);
  60.     SetBkMode(hdc,TRANSPARENT);
  61.    
  62.     //SS_RIGHT
  63.     UINT window_style=GetWindowLong(hwnd,GWL_STYLE);
  64.     if((UINT)(GetWindowLong(hwnd,GWL_STYLE)&(UINT)SS_RIGHT)==(UINT)SS_RIGHT)
  65.         DrawText(hdc,text,-1,&rect,DT_RIGHT);//DT_WORDBREAK|DT_EDITCONTROL|
  66.     else DrawText(hdc,text,-1,&rect,DT_WORDBREAK|DT_EDITCONTROL);
  67.    
  68.     DeleteObject(SelectObject(hdc,pre_font));
  69.     DeleteObject(SelectObject(hdc,pre_brush));
  70.    
  71.     free(text);
  72.     return 0;
  73. }

  74. LRESULT CALLBACK StaticProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  75. {
  76.     WNDPROC Ori_STCProc = (WNDPROC)GetWindowLong(hwnd,GWL_USERDATA);
  77.    
  78.     switch(message){
  79.     case WM_STATICCUSTOMDRAW:
  80.         {
  81.             LPDRAWITEMSTRUCT draw_struct = (LPDRAWITEMSTRUCT)lParam;
  82.             HDC hdc = draw_struct->hDC;
  83.             RECT rect;
  84.             
  85.             CopyRect(&rect,&(draw_struct->rcItem));
  86.             Static_draw(hwnd,hdc,rect,draw_struct->itemState);
  87.             return TRUE;
  88.         }
  89.     break;
  90.     case WM_ERASEBKGND:
  91.         {   
  92.             //avoid control flicker
  93.             return 1;
  94.         }
  95.     break;
  96.     }
  97.    
  98.     return CallWindowProc(Ori_STCProc,hwnd,message,wParam,lParam);
  99. }

  100. LRESULT CALLBACK ContainerProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  101. {
  102.     WNDPROC Ori_ParentProc = (WNDPROC)GetWindowLong(hwnd,GWL_USERDATA);
  103.    
  104.     switch(message){   
  105.     case WM_DRAWITEM:
  106.         {
  107.             LPDRAWITEMSTRUCT draw_struct = (LPDRAWITEMSTRUCT)lParam;
  108.             
  109.             if(draw_struct->CtlType == ODT_STATIC) {
  110.                 return SendMessage(draw_struct->hwndItem,WM_STATICCUSTOMDRAW,wParam,lParam);
  111.             }
  112.         }
  113.     break;
  114.     }

  115.     return CallWindowProc(Ori_ParentProc,hwnd,message,wParam,lParam);   
  116. }

  117. void regist_window(char* class_name,WNDPROC proc)
  118. {
  119.     WNDCLASSEX wndclass;

  120.     wndclass.cbSize=sizeof(wndclass);
  121.     wndclass.style = NULL;//CS_HREDRAW|CS_VREDRAW;
  122.     wndclass.lpfnWndProc = proc;
  123.     wndclass.cbClsExtra = 0;
  124.     wndclass.cbWndExtra = 0;
  125.     wndclass.hInstance = GInstance;
  126.     wndclass.hIcon = NULL;
  127.     wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
  128.     wndclass.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0,0,0));
  129.     wndclass.lpszMenuName = NULL;
  130.     wndclass.lpszClassName = class_name;
  131.     wndclass.hIconSm = NULL;

  132.     RegisterClassEx(&wndclass);
  133. }

  134. int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
  135. {
  136.     GInstance = hInstance;
  137.     char szClassName[]="BACK_PANEL";
  138.    
  139.     regist_window(szClassName,MainWndProc);
  140.         
  141.     HWND hwnd = CreateWindowEx(0,
  142.                                szClassName,
  143.                                szClassName,
  144.                                WS_THICKFRAME|WS_CAPTION|WS_OVERLAPPEDWINDOW|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_CLIPCHILDREN,
  145.                                200,
  146.                                50,
  147.                                800,
  148.                                600,
  149.                                NULL,
  150.                                NULL,
  151.                                hInstance,
  152.                                NULL);

  153.     if(hwnd == NULL)
  154.     {
  155.         MessageBox(NULL,"create windows error !","error",MB_OK);
  156.         return -1;
  157.     }
  158.    
  159.     ShowWindow(hwnd,nCmdShow);
  160.     UpdateWindow(hwnd);

  161.     MSG msg;
  162.     while (GetMessage(&msg, NULL, 0, 0)) {
  163.         TranslateMessage(&msg);
  164.         DispatchMessage(&msg);
  165.     }

  166.     return (int) msg.wParam;
  167. }

  168. LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  169. {
  170.     switch(message)
  171.     {
  172.     case WM_CREATE:
  173.         {
  174.             InitialWindow(hwnd);
  175.         }
  176.         break;
  177.     case WM_DESTROY:
  178.         PostQuitMessage(0);
  179.         return 0;
  180.         break;        
  181.     }
  182.     return DefWindowProc(hwnd,message,wParam,lParam);
  183. }

  184. void InitialWindow(HWND hwnd)
  185. {
  186.     HWND static_hwnd = CreateWindow(TEXT("Static"),
  187.                        "Text.",
  188.                        WS_BORDER|WS_CHILD|WS_VISIBLE|SS_OWNERDRAW|SS_RIGHT,
  189.                        50, 50, 250,315,
  190.                        hwnd,
  191.                        (HMENU)ID_STATIC_01,
  192.                        GInstance,
  193.                        NULL);
  194.                        
  195.     SetWindowLong(static_hwnd,GWL_USERDATA,(LONG)GetWindowLong(static_hwnd,GWL_WNDPROC));
  196.     SetWindowLong(static_hwnd,GWL_WNDPROC,(LONG)StaticProc);

  197.     SetWindowLong(hwnd,GWL_USERDATA,(LONG)GetWindowLong(hwnd,GWL_WNDPROC));
  198.     SetWindowLong(hwnd,GWL_WNDPROC,(LONG)ContainerProc);
  199.    
  200.     {
  201.     //SetWindowLong(static_hwnd,GWL_EXSTYLE,WS_EX_RIGHT|GetWindowLong(static_hwnd,GWL_EXSTYLE));//似乎与 GWL_EXSTYLE 没有关系
  202.    
  203.     char attribution_buffer[256]="";
  204.     UINT static_attri=(UINT)GetWindowLong(static_hwnd,GWL_STYLE);
  205.    
  206.     sprintf(attribution_buffer,"WS_BORDER:0x%08X\n"
  207.                                "WS_CHILDWINDOW:0x%08X\n"
  208.                                "WS_VISIBLE:0x%08X\n"
  209.                                "SS_OWNERDRAW:0x%08X\n"
  210.                                "SS_RIGHT:0x%08X\n"
  211.                                "Current style:0x%08X\n"
  212.                                "SIZEOF(UINT):%d\n"
  213.                                "SS_ENHMETAFILE:0x%08X\n"
  214.                                "SS_LEFT:0x%08X\n",
  215.                                WS_BORDER,WS_CHILDWINDOW,WS_VISIBLE,SS_OWNERDRAW,SS_RIGHT,
  216.                                static_attri,
  217.                                sizeof(UINT),
  218.                                SS_ENHMETAFILE,SS_LEFT);
  219.     HWND static_desc= CreateWindow(TEXT("Static"),
  220.                        attribution_buffer,
  221.                        WS_BORDER|WS_CHILD|WS_VISIBLE,
  222.                        310, 50, 250,315,
  223.                        hwnd,
  224.                        (HMENU)ID_STATIC_02,
  225.                        GInstance,
  226.                        NULL);
  227.     }                     
  228. }
复制代码




上一篇:VS2017单文档程序窗口分割没有CFormView基类的解决方法
下一篇:谁能够分享个修改内网IP地址的软件?
82_avatar_middle
最佳答案
14 
在线会员 发表于 2019-10-9 22:30:57 | 显示全部楼层
这个帖子中貌似有楼主要的答案,虽然我没完全看懂这个英文,哈哈
https://social.msdn.microsoft.com/Forums/vstudio/en-US/8b96363b-946b-41fa-bc45-e595861e3b22/win32-how-change-the-static-text-alignment?forum=vclanguage
50_avatar_middle
最佳答案
0 
ico_lz  楼主| 发表于 2019-10-10 09:28:40 | 显示全部楼层
love_cctry 发表于 2019-10-9 22:30
这个帖子中貌似有楼主要的答案,虽然我没完全看懂这个英文,哈哈
https://social.msdn.microsoft.com/Foru ...

从头翻到尾,最终的实现,他在控件之外用一个外部变量标识和识别对齐方式。这破坏了控件数据(样式)的独立性和完整性,不是一个理想的解决方案。

SS_OWERDRAW = 0x00000D = 0x00001101  ()本身是一个组合标识位)
= 0x00001000 | 0x00000100 | 0x00000001
50_avatar_middle
最佳答案
0 
ico_lz  楼主| 发表于 2019-10-10 10:14:10 | 显示全部楼层
某些类似的问题在这里也被提到了:
http://msgroups.net/microsoft.public.vc.mfc/ss_right-and-ss_ownerdraw/575661

一种凑合的使用方式是错误的使用(不可靠的复用)WS_EX_RIGHT 样式:

  1. void InitialWindow(HWND hwnd)
  2. {
  3.     HWND static_hwnd = CreateWindow(TEXT("Static"),
  4.                        "Text.",
  5.                        WS_BORDER|WS_CHILD|WS_VISIBLE|SS_OWNERDRAW,
  6.                        50, 50, 250,315,
  7.                        hwnd,
  8.                        (HMENU)ID_STATIC_01,
  9.                        GInstance,
  10.                        NULL);
  11. ......
  12. [color=Red]SetWindowLong(static_hwnd,GWL_EXSTYLE,WS_EX_RIGHT|GetWindowLong(static_hwnd,GWL_EXSTYLE));[/color]
  13. ......

  14. }

  15. int Static_draw(HWND hwnd,HDC hdc,RECT rect,UINT itemState)
  16. {
  17.     ......
  18.     [color=Red]if((UINT)(GetWindowLong(hwnd,GWL_EXSTYLE)&(UINT)WS_EX_RIGHT)==(UINT)WS_EX_RIGHT) [/color]
  19.         DrawText(hdc,text,-1,&rect,DT_RIGHT);//DT_WORDBREAK|DT_EDITCONTROL|
  20.     else DrawText(hdc,text,-1,&rect,DT_WORDBREAK|DT_EDITCONTROL);
  21.     ......
  22. }
复制代码

评分

参与人数 1驿站币 +2 热心值 +2 收起 理由
58_avatar_small thzzl + 2 + 2 赞一个!

查看全部评分

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号-4 )|网站地图wx_jqr

GMT+8, 2023-9-28 01:33

Powered by CcTry.CoM

© 2009-2021 cctry.com

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