zoukankan      html  css  js  c++  java
  • 纯c++实现之滚动窗口

    别在MFC了,先分析下,上图


    我们以左上角为坐标原点,用position_width和position_height来保存当前显示坐标。

    根据msdn说明,滚动条默认情况下的值在0~100之间。

    根据图可以知道positon_width的活动范围是0到canvas_width-screen-width,另一边类似。

    所以有恒等式1:position_width/(canvas_width-screen_width) = hb_pos/100,其中hb_pos是水平方向滚动条当前值。

    滚动块长度公式2:screen_width/canvas_width = 滚动块长度/滚动条可滚动区域长度,滚动条可滚动区域长度大概是screen_width-40差不多,可以设置大写留余地。


    下面直接上完整代码,可以运行的,只实现了拖动滚动块事件,其他事件自己补充吧

      1. #include <windows.h>  
      2.   
      3. #define  IDC_CANVAS                  200  
      4.   
      5. HWND hwnd_screen = NULL;//屏幕句柄,这里的屏幕既是我们创建的顶级窗口  
      6. HWND hwnd_canvas = NULL;//画布句柄  
      7. HINSTANCE   Ghinstance = NULL;//程序实例  
      8.   
      9. //注意:以下提到的“屏幕”指的都是我们创建的模拟屏幕,也就是顶级窗口,而不是我们计算机的屏幕  
      10.   
      11. int         canvas_width        = 2000;//画布长度  
      12. int         canvas_height       = 1500;//画布宽度  
      13.   
      14. int         screen_width        = 0;//屏幕长度  
      15. int         screen_height       = 0;//屏幕宽度  
      16.   
      17. int         position_width      = 0;//当前位置的横坐标  
      18. int         position_height     = 0;//当前位置的纵坐标  
      19.   
      20. int         hb_pos              = 0;//竖直方向滚动条当前位置  
      21. int         vb_pos              = 0;//水平方向滚动条当前位置  
      22.   
      23.   
      24. LRESULT CALLBACK ScreenProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);//屏幕事件处理函数  
      25. LRESULT CALLBACK CanvasProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);//画布事件处理函数  
      26.   
      27.   
      28. //入口函数  
      29. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {  
      30.   
      31. //========================================创建屏幕begin==================================================     
      32.     WNDCLASSEX wc;  
      33.     MSG Msg;  
      34.   
      35.     memset(&wc,0,sizeof(wc));  
      36.     wc.cbSize        = sizeof(WNDCLASSEX);  
      37.     wc.lpfnWndProc   = ScreenProc;  
      38.     wc.hInstance     = hInstance;  
      39.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);  
      40.     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);  
      41.     wc.lpszClassName = "WindowClass";  
      42.     wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);  
      43.   
      44.     if(!RegisterClassEx(&wc)) {  
      45.         MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);  
      46.         return 0;  
      47.     }  
      48.       
      49.     //程序实例和屏幕句柄放到全局变量里  
      50.     Ghinstance = hInstance;  
      51.     hwnd_screen = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,  
      52.         CW_USEDEFAULT,  
      53.         CW_USEDEFAULT,  
      54.         800,  
      55.         600,  
      56.         NULL,NULL,hInstance,NULL);  
      57.   
      58.     if(hwnd_screen == NULL) {  
      59.         MessageBox(NULL, "Screen Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);  
      60.         return 0;  
      61.     }  
      62.       
      63. //========================================创建屏幕end==================================================    
      64.       
      65.       
      66. //你也可以把创建画布的过程放到屏幕的WM_CREATE事件中,放这里是使读者思路能清晰些     
      67. //========================================创建画布begin==================================================  
      68.     wc;  
      69.   
      70.     memset(&wc,0,sizeof(wc));  
      71.     wc.cbSize        = sizeof(WNDCLASSEX);  
      72.     wc.lpszClassName = "Canvas";  
      73.     wc.lpfnWndProc   = CanvasProc;  
      74.     wc.hInstance     = Ghinstance;//这里可以直接使用全局变量了  
      75.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);  
      76.     wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);  
      77.       
      78.     if(!RegisterClassEx(&wc)) {  
      79.         MessageBox(NULL, "Canvas Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);  
      80.         return 0;  
      81.     }                 
      82.       
      83.     hwnd_canvas= CreateWindow(  
      84.             "Canvas",  
      85.             "",  
      86.             WS_CHILD | WS_VISIBLE | WS_BORDER,  
      87.             0, 0, canvas_width, canvas_height,  
      88.             hwnd_screen,//这里可以直接使用全局变量了,注意,如果是放屏幕的WM_CREATE里面,这时候是还不能使用这个全局变量的,WM_CREATE事件结束后CreateWindow方法才会返回创建窗口的句柄  
      89.             (HMENU)IDC_CANVAS,  
      90.             Ghinstance,//这里可以直接使用全局变量了  
      91.             0  
      92.             );  
      93.       
      94.     if(hwnd_canvas == NULL) {  
      95.         MessageBox(NULL, "Canvas Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);  
      96.         return 0;  
      97.     }     
      98.   
      99. //========================================创建画布end==================================================  
      100.       
      101.     //该显示的显示  
      102.     ShowWindow(hwnd_screen, nCmdShow);  
      103.     UpdateWindow(hwnd_screen);  
      104.       
      105.     //该显示的显示      
      106.     ShowWindow(hwnd_canvas, SW_SHOW);  
      107.     UpdateWindow(hwnd_canvas);      
      108.       
      109.        
      110.     //消息循环  
      111.     while(GetMessage(&Msg, NULL, 0, 0) > 0) {  
      112.         TranslateMessage(&Msg);  
      113.         DispatchMessage(&Msg);  
      114.     }  
      115.     return Msg.wParam;  
      116. }  
      117.   
      118. //屏幕的事件  
      119. LRESULT CALLBACK ScreenProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {  
      120.       
      121.     //只需要处理WM_SIZE、WM_HSCROLL、WM_VSCROLL三个消息  
      122.     switch(Message) {  
      123.       
      124.         //窗口大小改变时,更新全局变量中的屏幕大小,更新滚动条上滚动块的位置  
      125.         case WM_SIZE: {  
      126.               
      127.             //更新屏幕大小begin-----------------------------  
      128.             screen_width = LOWORD (lParam);  
      129.             screen_height = HIWORD (lParam);  
      130.             //更新屏幕大小end-----------------------------  
      131.               
      132.             //更新滚动条上滚动块的位置begin----------------------  
      133.             hb_pos = position_width * 100 / (canvas_width - screen_width);//根据恒等式1  
      134.             vb_pos = position_height * 100 / (canvas_height - screen_height);  
      135.               
      136.             SCROLLINFO  si;  
      137.             si.cbSize=sizeof(SCROLLINFO);             
      138.             si.fMask=SIF_POS;             
      139.                           
      140.             si.nPos = vb_pos;  
      141.             SetScrollInfo(hwnd_screen,SB_VERT,&si,true);  
      142.                           
      143.             si.nPos = hb_pos;  
      144.             SetScrollInfo(hwnd_screen,SB_HORZ,&si,true);              
      145.             //更新滚动条上滚动块的位置end----------------------  
      146.               
      147.               
      148.             //其实还应该更新滚动条上滚动块的长度,这里先忽略吧  
      149.             //int hb_length = GValue::s_width * (GValue::s_width - 40) / GValue::c_width;//根据恒等式2  
      150.             //int vb_length = GValue::s_height * (GValue::s_height - 40) / GValue::c_height;  
      151.               
      152.             break;  
      153.         }  
      154.           
      155.           
      156.         //水平方向滚动条事件  
      157.         case WM_HSCROLL : {       
      158.               
      159.             SCROLLINFO  si;  
      160.             si.cbSize=sizeof(SCROLLINFO);  
      161.             si.fMask=SIF_ALL;  
      162.             GetScrollInfo(hwnd_screen,SB_HORZ,&si);//先拿滚动条信息  
      163.               
      164.             switch(LOWORD(wParam)){//这里只处理按下滚动条拖动的事件,其他滚动条事件自己实现吧  
      165.               
      166.                 //分析可知按住滚动条拖动过程中,需要修改当前位置、然后基于当前位置移动画布,最后修改滚动条位置(你不修改的话视觉效果上会弹回去的)、  
      167.                 case SB_THUMBTRACK: {                                         
      168.                     position_width = si.nTrackPos * (canvas_width - screen_width) / 100;//更改当前位置          
      169.                     MoveWindow(hwnd_canvas, 0 - position_width, 0 - position_height, canvas_width, canvas_height, true);//移动画布  
      170.                       
      171.                     si.nPos=si.nTrackPos;  
      172.                     break;  
      173.                 }  
      174.                   
      175.                 //TODO 滚动条的其他事件               
      176.                   
      177.                 default: {  
      178.                     break;  
      179.                 }  
      180.             }  
      181.               
      182.             //回写滚动条滚动块的位置,时视觉上正常  
      183.             si.fMask=SIF_POS;  
      184.             SetScrollInfo(hwnd_screen, SB_HORZ, &si, true);           
      185.               
      186.             break;  
      187.         }  
      188.           
      189.         //竖直方向滚动条事件,与上面相似不解释了  
      190.         case WM_VSCROLL : {  
      191.               
      192.             SCROLLINFO  si;  
      193.             si.cbSize=sizeof(SCROLLINFO);  
      194.             si.fMask=SIF_ALL;  
      195.             GetScrollInfo(hwnd_screen, SB_VERT, &si);  
      196.               
      197.             switch(LOWORD(wParam)){  
      198.                 case SB_THUMBTRACK: {  
      199.                       
      200.                     position_height = si.nTrackPos * (canvas_height - screen_height) / 100;  
      201.                     MoveWindow(hwnd_canvas, 0 - position_width, 0 - position_height, canvas_width, canvas_height, true);  
      202.                       
      203.                     si.nPos=si.nTrackPos;  
      204.                     break;  
      205.                 }  
      206.                   
      207.                 default: {  
      208.                     break;  
      209.                 }  
      210.             }  
      211.               
      212.             si.fMask=SIF_POS;  
      213.             SetScrollInfo(hwnd_screen, SB_VERT, &si, true);           
      214.               
      215.             break;  
      216.         }  
      217.           
      218.         //鼠标滚轮  
      219. /*      case WM_MOUSEWHEEL : { 
      220.              
      221.             //向下 
      222.             if(HIWORD(wParam) < 0) { 
      223.                 vb_pos = vb_pos + 10; 
      224.                 if(vb_pos > 100) { 
      225.                     vb_pos = 0; 
      226.                 }                
      227.             } else { 
      228.                 vb_pos = vb_pos - 10; 
      229.                 if(vb_pos < 0) { 
      230.                     vb_pos = 0; 
      231.                 } 
      232.             } 
      233.              
      234.             break; 
      235.         } 
      236. */        
      237.               
      238.         case WM_CLOSE: {  
      239.             DestroyWindow(hwnd);  
      240.             break;  
      241.         }  
      242.           
      243.         case WM_DESTROY: {  
      244.             PostQuitMessage(0);  
      245.             break;  
      246.         }  
      247.           
      248.         default:  
      249.             return DefWindowProc(hwnd, Message, wParam, lParam);  
      250.     }  
      251.     return 0;  
      252. }  
      253.   
      254. //窗口的事件  
      255. LRESULT CALLBACK CanvasProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {  
      256.       
      257.     switch(Message) {  
      258.           
      259.         //从画布左上角到右下角画一条线,以便观察滚动效果  
      260.         case WM_PAINT: {  
      261.             PAINTSTRUCT ps;  
      262.             HDC hdc;      
      263.               
      264.             RECT rc;  
      265.             GetClientRect(hwnd_canvas, &rc);  
      266.   
      267.             hdc = BeginPaint(hwnd_canvas, &ps);  
      268.               
      269.             MoveToEx(hdc, 0 , 0 , NULL);  
      270.             LineTo(hdc, rc.right, rc.bottom);  
      271.               
      272.             EndPaint(hwnd_canvas, &ps);  
      273.               
      274.             break;  
      275.         }     
      276.       
      277.         case WM_CLOSE: {  
      278.             DestroyWindow(hwnd);  
      279.             break;  
      280.         }  
      281.           
      282.         case WM_DESTROY: {  
      283.             PostQuitMessage(0);  
      284.             break;  
      285.         }  
      286.           
      287.         default:  
      288.             return DefWindowProc(hwnd, Message, wParam, lParam);  
      289.     }  
      290. }     
  • 相关阅读:
    pandas Dataframe filter
    process xlsx with pandas
    data manipulate in excel with easyExcel class
    modify registry in user environment
    add number line in vim
    java import webservice
    ctypes MessageBoxA
    music 163 lyrics
    【python实例】自动贩卖机
    【python基础】sys模块(库)方法汇总
  • 原文地址:https://www.cnblogs.com/zhoug2020/p/6076185.html
Copyright © 2011-2022 走看看