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. }     
  • 相关阅读:
    javascript得知
    一旦配置oracle em经验
    windows 下一个mysql password忘记改变
    彩色图像--图像切 色彩空间切割
    Delphi 6 Web Services初步评估之三(转)
    Delphi 用Web App Debugger简单调试ISAPI 转
    Delphi socket() 函数的应用
    用Delphi实现WinSocket高级应用
    delphi编写winsocket的流程
    Delphi使用NativeXml访问XML文件
  • 原文地址:https://www.cnblogs.com/zhoug2020/p/6076185.html
Copyright © 2011-2022 走看看