基于win32的windows画板程序

 

功能设计如下:

 

1.Graphics菜单中可选择图形,支持Rectangle, Circle, Line,选择对应图形,则相应菜单项前面加上选中标志;

 

 

2.Options菜单中包含以下选项
  a.Color,设置颜色,选中此项,则弹出如下图所示对话框

 

 


  进入对话框时,默认值为当前颜色,单击"确定"后,则以选中颜色为当前前景色和填充色进行图形绘制
  
  b.Width 设置线条的宽度,选中此项则弹出如下对话框


入对话框时,默认值为当前所使用的宽度值,单击"确定"按钮后,则以设定的值为当前宽度值进行图形绘制,宽度值范围1-10(注意:每次打开此对话框,显示当前正在使用的宽度值)

 

 

c.Fill和Opaque,设置填充的方式,Fill表示填充,Opaque表示透明,此两项为二选一,选中后,相应项目前面加上选中标志

 

 

 
3.绘制操作,单击鼠标左键,保持左键按下,移动鼠标,则在两点按下左键坐标点和当前鼠标坐标点间绘制出相应选中的图形。

 

 

4.Operation菜单

 

 

  a.Reverse菜单项(快捷键Ctrl + R),执行将图形沿水平方向翻转180度

 

 

  b.Reset菜单项(快捷键Ctrl + S),将图形从翻转状态恢复到正常状态

 

 

5.右键快捷菜单与4中a,b相同

 

 

程序源代码:

 

// exam.cpp : Defines the entry point for the application.
//
 
#include "stdafx.h"
#include "resource.h"
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <commdlg.h>
#include <commctrl.h>
 
#define MAX_LOADSTRING 100
 
// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                              // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];                                // The title bar text
 
CHOOSECOLOR  chc;
bool IsDraw=false;
bool IsReverse=false;
int g_iCount=0;
 
RECT rect1;
int Graphics=0;
COLORREF clref[16]={0x00ff0000};
bool IsFill=false;
int iWidth=0;
 
struct DATASTORE        //图形数据存储结构
{
    RECT rect1;         //起点,终点
    int Graphics;       //图形形状
    COLORREF pColor;        //画笔颜色
    bool IsFill;            //画笔风格
    int iWidth;         //画笔宽度
    //int bColor;           //画刷颜色
};
 
struct DATASTORE DataStore[1000];  
 
// Foward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    Width(HWND, UINT, WPARAM, LPARAM);
 
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;
 
    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_EXAM, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);
 
    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
 
    hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_EXAM);
 
    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
 
    return msg.wParam;
}
 
 
 
//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
 
    wcex.cbSize = sizeof(WNDCLASSEX);
 
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, (LPCTSTR)IDI_EXAM);
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = (LPCSTR)IDC_EXAM;
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
 
    return RegisterClassEx(&wcex);
}
 
//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
 
   hInst = hInstance; // Store instance handle in our global variable
 
   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
 
   if (!hWnd)
   {
      return FALSE;
   }
 
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);
 
   return TRUE;
}
 
//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hDC;
    HBRUSH hBrush;
    HPEN hPen;
    HMENU hMenu;
    TCHAR szHello[MAX_LOADSTRING];
    LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
     
 
 
    WORD x,y;
 
    x = LOWORD(lParam);     //得到鼠标的位置.
    y = HIWORD(lParam);
 
    hMenu=GetMenu(hWnd);
    switch (message)
    {
 
        case WM_CREATE:        
        //选择颜色通用对话框
        chc.lStructSize = sizeof(CHOOSECOLOR);      //结构大小
        chc.hwndOwner = hWnd;                       //父窗口句柄
        chc.rgbResult = 0;                          //设定默认颜色
        chc.lpCustColors = clref;                   //指向用户自定义颜色数组的指针
        chc.Flags = 0;                              //标志
        chc.lCustData = 0;                         
        chc.lpfnHook = NULL;                        //钩子函数指针.同对话框处理函数功能一样
        chc.lpTemplateName = NULL;
 
        break;
        case WM_COMMAND:
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // Parse the menu selections:
            switch (wmId)
            {
                case IDM_RECTANGLE:
                    CheckMenuItem(hMenu,IDM_RECTANGLE,MF_CHECKED);
                    CheckMenuItem(hMenu,IDM_CIRCLE,MF_UNCHECKED);
                    CheckMenuItem(hMenu,IDM_LINE,MF_UNCHECKED);
                    Graphics=2;
                    break;
                case IDM_CIRCLE:
                    CheckMenuItem(hMenu,IDM_CIRCLE,MF_CHECKED);
                    CheckMenuItem(hMenu,IDM_RECTANGLE,MF_UNCHECKED);
                    CheckMenuItem(hMenu,IDM_LINE,MF_UNCHECKED);
                    Graphics=1;
                    break;
                case IDM_LINE:
                    CheckMenuItem(hMenu,IDM_LINE,MF_CHECKED);
                    CheckMenuItem(hMenu,IDM_RECTANGLE,MF_UNCHECKED);
                    CheckMenuItem(hMenu,IDM_CIRCLE,MF_UNCHECKED);
                    Graphics=0;
                    break;
                case IDM_COLOR:
                    ChooseColor(&chc);
                    break;
                case IDM_WIDTH:
                     DialogBox(hInst, (LPCTSTR)IDD_WIDTH, hWnd, (DLGPROC)Width);
 
                    break;
                case IDM_FILL:
                    CheckMenuItem(hMenu,IDM_FILL,MF_CHECKED);
                    CheckMenuItem(hMenu,IDM_OPAQUE,MF_UNCHECKED);
                    IsFill=true;
                    break;
                case IDM_OPAQUE:
                    CheckMenuItem(hMenu,IDM_OPAQUE,MF_CHECKED);
                    CheckMenuItem(hMenu,IDM_FILL,MF_UNCHECKED);
                    IsFill=false;
 
                    break;
                case IDM_REVERSE:
                    IsReverse=true;
                    InvalidateRect(hWnd,NULL,TRUE);
                    break;
                case IDM_RESET:
                    IsReverse=false;
                    InvalidateRect(hWnd,NULL,TRUE);
                    break;
 
                case IDM_ABOUT:
                   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
                   break;
                case IDM_EXIT:
                   DestroyWindow(hWnd);
                   break;
                default:
                   return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        case WM_LBUTTONDOWN:
            IsDraw=true;
            rect1.left = x;        
            rect1.top = y;
            //MoveToEx(hDC,rect1.left = x,rect1.top = y,NULL);
            break;
        case WM_LBUTTONUP:
            DataStore[g_iCount].rect1 = rect1;
            //DataStore[g_iCount].ptEnd = ptEnd;
            DataStore[g_iCount].Graphics = Graphics;
            DataStore[g_iCount].pColor = chc.rgbResult;
            DataStore[g_iCount].IsFill = IsFill;
            DataStore[g_iCount].iWidth = iWidth;
            //DataStore[g_iCount].bColor = bSelection;
            g_iCount++;
            IsDraw=false;
            break;
        case WM_MOUSEMOVE:         
            rect1.right = x;       
            rect1.bottom = y;
            if(IsDraw==true)
            {
                InvalidateRect(hWnd,NULL,TRUE); //发出重绘信息.
                UpdateWindow(hWnd);
            }
            break;
        case WM_RBUTTONDOWN:
            POINT point;
            point.x=LOWORD(lParam);
            point.y=HIWORD(lParam);
            ClientToScreen(hWnd,&point);
            TrackPopupMenu(GetSubMenu(hMenu,3),TPM_LEFTALIGN,point.x,point.y,0,hWnd,NULL);
            break;
        case WM_PAINT:
            hDC = BeginPaint(hWnd, &ps);
            RECT rt;
            GetClientRect(hWnd, &rt);
 
            SetMapMode(hDC,MM_ANISOTROPIC);
            SetViewportOrgEx(hDC,(rt.left+rt.right)/2,(rt.bottom+rt.right)/2,NULL); 
            SetViewportOrgEx(hDC,0,0,NULL);
 
 
            int i;
            for(i = 0; i <g_iCount; i++)
            {
                if(IsReverse==true)
                {
                    SetViewportExtEx(hDC,1,-1,0);
                    SetViewportOrgEx(hDC,0,rt.bottom-rt.top ,NULL);
                }
                else
                {
                    SetViewportExtEx(hDC,1,1,0);
                    SetViewportOrgEx(hDC,0,0,NULL);
                }
 
                hPen=CreatePen(PS_SOLID,DataStore[i].iWidth,DataStore[i].pColor );
                if(DataStore[i].IsFill==true)
                {
                    hBrush=CreateSolidBrush(DataStore[i].pColor);
                }
                else
                {
                    hBrush=(HBRUSH)GetStockObject(NULL_BRUSH);
                }
                SelectObject(hDC,hBrush);
                SelectObject(hDC,hPen);
 
         
                if(DataStore[i].Graphics==0)
                {
                    MoveToEx(hDC,DataStore[i].rect1.left,DataStore[i].rect1.top,NULL);
                    LineTo(hDC,DataStore[i].rect1.right,DataStore[i].rect1.bottom);
                     
                }
                if(DataStore[i].Graphics==1)
                {  
 
                    Ellipse(hDC,DataStore[i].rect1.left,DataStore[i].rect1.top,DataStore[i].rect1.right,DataStore[i].rect1.bottom);
                }
                if(DataStore[i].Graphics==2)
                {  
 
                    Rectangle(hDC,DataStore[i].rect1.left,DataStore[i].rect1.top,DataStore[i].rect1.right,DataStore[i].rect1.bottom);
                }
                DeleteObject(hPen);
                DeleteObject(hBrush);
             
                 
            }
 
 
 
            hPen=CreatePen(PS_SOLID,iWidth,chc.rgbResult);
            if(IsFill==true)
            {
                hBrush=CreateSolidBrush(chc.rgbResult);
            }
            else
            {
                hBrush=(HBRUSH)GetStockObject(NULL_BRUSH);
            }
            SelectObject(hDC,hBrush);
            SelectObject(hDC,hPen);
            // TODO: Add any drawing code here...
             
 
            //DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
            if (IsDraw==true)
            {
                if(Graphics==0)
                {
                    MoveToEx(hDC,rect1.left,rect1.top,NULL);
                    LineTo(hDC,rect1.right,rect1.bottom);
                     
                }
                if(Graphics==1)
                {  
 
                    Ellipse(hDC,rect1.left,rect1.top,rect1.right,rect1.bottom);
                }
                if(Graphics==2)
                {  
 
                    Rectangle(hDC,rect1.left,rect1.top,rect1.right,rect1.bottom);
                }
            }
            DeleteObject(hPen);
            DeleteObject(hBrush);
 
 
            EndPaint(hWnd, &ps);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}
 
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_INITDIALOG:
                return TRUE;
 
        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return TRUE;
            }
            break;
    }
    return FALSE;
}
LRESULT CALLBACK Width(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    HWND    hWndSlider=GetDlgItem(hDlg, IDC_SLIDER);
    switch (message)
    {
 
        case WM_INITDIALOG:
            SendMessage(hWndSlider, TBM_SETTICFREQ , 1, 0);
            SendMessage(hWndSlider, TBM_SETRANGE, 1, MAKELONG(1,10));
             
             
            return TRUE;
        case WM_SHOWWINDOW:
            SendMessageW(hWndSlider,TBM_SETPOS, 1,iWidth);//设置slider控件
            break;
 
        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK)
            {
                 
                iWidth= SendMessageW(hWndSlider, TBM_GETPOS, 0, 0);
                EndDialog(hDlg, LOWORD(wParam));
                 
                return TRUE;
            }
            if (LOWORD(wParam) == IDCANCEL)
            {
                 
                EndDialog(hDlg, LOWORD(wParam));
                 
                return TRUE;
            }
             
            break;
    }
    return FALSE;
}

 

  

 

posted @   左昱_leftshine  阅读(2315)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示