(六)绘图,文本编程,定时器,菜单,图标icon,消息类型

1,简单绘图

  画直线

    a,鼠标按下和抬起       

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    m_myPoint = point;

    CView::OnLButtonDown(nFlags, point);
}
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    CClientDC dc(this);
    dc.MoveTo(m_myPoint);
    dc.LineTo(point);

    CView::OnLButtonUp(nFlags, point);
}

    b,CPaintDC 只能在OnPaint 中使用

      CClientDC 在任何地方都可以使用

    c,起点和终点

        MoveTo  移动当前位置

        LineTo  从当前位置到一点画直线,但不包括那个点

    d,选择所属类 -> 右击 -> 添加变量,这种方法会自动帮你初始化变量

    

  连续的线

    鼠标移动事件

// CDrawView 消息处理程序


void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    m_myPoint = point;
    m_isPressed = true;

    CView::OnLButtonDown(nFlags, point);
}


void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
#if 0
    CClientDC dc(this);
    dc.MoveTo(m_myPoint);
    dc.LineTo(point);
#endif
    m_isPressed = false;
    CView::OnLButtonUp(nFlags, point);
}


void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    if (m_isPressed) {
        CClientDC dc(this);
        dc.MoveTo(m_myPoint);
        dc.LineTo(point);

        // 终点作为起点
        m_myPoint = point;
    }

    CView::OnMouseMove(nFlags, point);
}

void CDrawView::OnDraw(CDC* pDC)
{
    CDrawDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: 在此处为本机数据添加绘制代码

    // 画圆
    /*
    参数: x1 指定椭圆外接矩形左上角的X逻辑坐标。  
    y1 指定椭圆外接矩形左上角的Y逻辑坐标。  
    x2 指定椭圆外接矩形右下角的X逻辑坐标。  
    y2 指定椭圆外接矩形右下角的Y逻辑坐标。 
    */
    pDC->Ellipse(20,20,120,120);

    // 画刷
    CBrush brush(RGB(255, 0, 0));
    pDC->SelectObject(&brush);
    pDC->Ellipse(20, 20, 120, 120);
}

2,位图的 使用

 

 

// CDrawView 绘图

void CDrawView::OnDraw(CDC* pDC)
{
    CDrawDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: 在此处为本机数据添加绘制代码

    // 画圆
    /*
    参数: x1 指定椭圆外接矩形左上角的X逻辑坐标。  
    y1 指定椭圆外接矩形左上角的Y逻辑坐标。  
    x2 指定椭圆外接矩形右下角的X逻辑坐标。  
    y2 指定椭圆外接矩形右下角的Y逻辑坐标。 
    */
    pDC->Ellipse(20,20,120,120);

    // 画刷
    CBrush brush(RGB(255, 0, 0));
    pDC->SelectObject(&brush);
    pDC->Ellipse(20, 20, 120, 120);

    // 定义一个位图对象
    CBitmap bitmap;
    bitmap.LoadBitmapW(IDB_BITMAP1);

    CBrush brush2(&bitmap);
    pDC->SelectObject(&brush2);
    pDC->Ellipse(120,120,240,240);

}

3,字体

// CDrawView 绘图

void CDrawView::OnDraw(CDC* pDC)
{
    CDrawDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: 在此处为本机数据添加绘制代码

    // 画圆
    /*
    参数: x1 指定椭圆外接矩形左上角的X逻辑坐标。  
    y1 指定椭圆外接矩形左上角的Y逻辑坐标。  
    x2 指定椭圆外接矩形右下角的X逻辑坐标。  
    y2 指定椭圆外接矩形右下角的Y逻辑坐标。 
    */
    pDC->Ellipse(20,20,120,120);

    // 画刷
    CBrush brush(RGB(255, 0, 0));
    pDC->SelectObject(&brush);
    pDC->Ellipse(20, 20, 120, 120);

    // 定义一个位图对象
    CBitmap bitmap;
    bitmap.LoadBitmapW(IDB_BITMAP1);

    CBrush brush2(&bitmap);
    pDC->SelectObject(&brush2);
    pDC->Ellipse(120,120,240,240);

    CFont font;
    font.CreatePointFont(500, TEXT("楷体"));
    pDC->SelectObject(&font);
    pDC->TextOutW(100,100,TEXT("hello world"));
}

4,文本编程

  1,创建插入符CWnd::CreateSolidCaret()

    a,创建CWnd::CreateSolidCaret()

    b,显示CWnd::ShowCaret()

    c,插入符的高度是根据字体的高度来确定

      获取字体信息CDC::GetTextMetrics()

    d,设置插入符的位置CWnd::SetCaretPos()

  2,在字符消息处理函数中写字

    a,写字CDC::TextOutW()

    b,获取字符串的尺寸信息CDC::GetTextExtent()

    c,截取字符串(CString)左边指定长度的字符 str = str.Left(str.GetLength() - 1);

int CEditorView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  在此添加您专用的创建代码

    // 获取字体信息
    CClientDC dc(this);
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);

    // 继承与CWnd
    CreateSolidCaret(tm.tmAveCharWidth / 8,tm.tmHeight); // 创建插入符

    ShowCaret();
    return 0;
}

 写字

// CEditorView 消息处理程序


int CEditorView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  在此添加您专用的创建代码

    // 获取字体信息
    CClientDC dc(this);
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);

    // 继承与CWnd
    CreateSolidCaret(tm.tmAveCharWidth / 8,tm.tmHeight); // 创建插入符

    ShowCaret();
    return 0;
}


void CEditorView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    SetCaretPos(point);//设置插入符的位置

    m_point = point;// 保存点的坐标

    m_str.Empty(); // 清空上一次的数据

    CView::OnLButtonDown(nFlags, point);
}

// 点击键盘,启动调用
void CEditorView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    
    CClientDC dc(this);

    // 换行和退格
    if (nChar == VK_RETURN) {
        // 获取字体信息
        TEXTMETRIC tm;
        dc.GetTextMetrics(&tm);

        m_point.y = m_point.y + tm.tmHeight;
        m_str.Empty();
    }
    else if (nChar == VK_BACK) {
        COLORREF color = dc.GetBkColor();// 获取背景色
        COLORREF oldColor = dc.SetTextColor(color);// 设置写字的颜色,返回以前的文本颜色的 RGB 值。

        // 白色重写一次文本
        dc.TextOutW(m_point.x, m_point.y, m_str);
        // 去掉最后一个字符
        m_str = m_str.Left(m_str.GetLength() - 1);

        dc.SetTextColor(oldColor);
    }
    else {
        m_str += (TCHAR)nChar;
    }

    CSize size = dc.GetTextExtent(m_str); // 可以获取文本的宽度和长度
    // 移动光标
    CPoint pos;
    pos.x = m_point.x + size.cx;
    pos.y = m_point.y;
    SetCaretPos(pos);

    dc.TextOutW(m_point.x, m_point.y, m_str);

    CView::OnChar(nChar, nRepCnt, nFlags);
}

5,菜单

1,菜单命令响应函数

  a,弹式菜单,ID不可编辑,按下去,弹出一个菜单项

  

  b,非弹式菜单,ID可编辑

  

  c,菜单响应命令消息的路由(顺序)

  

void CMainFrame::OnTestDemo()
{
    // TODO: 在此添加命令处理程序代码
    MessageBox(TEXT("Frame"));
}
void CTimerApp::OnTestDemo()
{
    // TODO: 在此添加命令处理程序代码
    AfxMessageBox(TEXT("app"));
}
void CTimerDoc::OnTestDemo()
{
    // TODO: 在此添加命令处理程序代码
    AfxMessageBox(TEXT("doc"));
}
void CTimerView::OnTestDemo()
{
    // TODO: 在此添加命令处理程序代码
    MessageBox(TEXT("view"));
}

菜单命令响应路由

视图--文档-框架-应用程序

  d,消息类型

    非标准消息

    命令消息WM_COMMAND:菜单处理函数选中;通告消息,点击按钮,处理函数CCmdTarget, CWnd子类能接收到非标准消息

    标准消息  WM_XXXX ,属性->消息  CWnd子类才能接收到标准消息,CCmdTarget不能接收标准消息

CMainFrame::CMainFrame()
{
    // TODO: 在此添加成员初始化代码
    m_bAutoMenuEnable = false;
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
        !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
    {
        TRACE0("未能创建工具栏
");
        return -1;      // 未能创建
    }

    if (!m_wndStatusBar.Create(this))
    {
        TRACE0("未能创建状态栏
");
        return -1;      // 未能创建
    }
    m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

    // TODO: 如果不需要可停靠工具栏,则删除这三行
    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockControlBar(&m_wndToolBar);

    // 标志
    // 获取菜单
    //获取主菜单
    CMenu *menu = GetMenu();
    // 获取子菜单
    CMenu *fileMenu = menu->GetSubMenu(0);
    // 标志新建
    fileMenu->CheckMenuItem(0, MF_BYPOSITION | MF_CHECKED);

    fileMenu->CheckMenuItem(ID_FILE_OPEN, MF_BYCOMMAND | MF_CHECKED);

    // 设置默认项 加粗,一个菜单项只有一个默认菜单
    // ID  FALSE
    // 位置 TRUE
    fileMenu->SetDefaultItem(ID_FILE_SAVE, FALSE);
    fileMenu->SetDefaultItem(3, TRUE);

    // 变灰
    // 需要把CFrameWnd::m_bAutoMenuEnable 设置 false
    fileMenu->EnableMenuItem(ID_FILE_PRINT, MF_BYCOMMAND | MF_DISABLED); // MF_GRAYED 与 MF_DISABLED等价

    return 0;
}

菜单更新机制

void CMainFrame::OnUpdateTest1A(CCmdUI *pCmdUI)
{
    // TODO: 在此添加命令更新用户界面处理程序代码
    if (m_update) {
        pCmdUI->Enable(TRUE);
    }
    else {
        pCmdUI->Enable(FALSE);
    }
}


void CMainFrame::OnTest1B()
{
    // TODO: 在此添加命令处理程序代码
    m_update = !m_update;
}
CMainFrame::CMainFrame()
{
    // TODO: 在此添加成员初始化代码
    m_bAutoMenuEnable = false;
}

// CMenuView 消息处理程序


void CMenuView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    // 获取主菜单
    CMenu menu;
    menu.LoadMenuW(IDR_MENU1);
    // 获取子菜单
    CMenu *subMenu = menu.GetSubMenu(1);

    ClientToScreen(&point);
    // 子菜单作为快捷菜单,右击菜单
    subMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, point.x, point.y, this);

    CView::OnLButtonDown(nFlags, point);
}

点击

6,定时器实现渐变色

字体渐变

  1,定时器的使用

    a,设置定时器:CWnd::SetTimer()

    b,关闭定时器:CWnd::KillTimer()

    c,定时器消息:WM_TIMER

  2,视图类中的OnDraw()中,写字 CDC::TextOutW()

  3,指定区域写字:CDC::DrawText()

  4,让窗口失效,产生WM_PAINT ,间接调用OnDraw()函数:CWnd::Invalidate

// CTimerView 消息处理程序


int CTimerView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  在此添加您专用的创建代码

    // 设置定时器
    // 1:定时器ID
    // 200:时间间隔,ms
    // NULL:使用系统默认的处理函数,每隔...毫秒,触发WM_TIMER
    SetTimer(1, 1000, NULL);

    return 0;
}


void CTimerView::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    if (nIDEvent == 1) {
        static int i = 0;
        i++;
        CString str;
        str.Format(TEXT("%d"), i);
        
        if (i >= 5) {
            KillTimer(1);
        }
        MessageBox(str);
    }

    CView::OnTimer(nIDEvent);
}
// CTimerView 消息处理程序


int CTimerView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  在此添加您专用的创建代码

    // 设置定时器
    // 1:定时器ID
    // 200:时间间隔,ms
    // NULL:使用系统默认的处理函数,每隔...毫秒,触发WM_TIMER
    SetTimer(1, 200, NULL);

    return 0;
}


void CTimerView::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    if (nIDEvent == 1) {
        static int w = 0;
        w += 5;

        CString str = TEXT("在此添加消息处理程序代码和/或调用默认值");

        CClientDC dc(this);
        CSize size = dc.GetTextExtent(str);
        // 如果宽度大于字符串的宽度,重新开始
        if (w > size.cx) {
            w = 0;
            Invalidate();// 刷新窗口,相当于Qt里面的Update()
        }
        int x = 30;
        int y = 30;

        // 黑色写一次
        dc.TextOutW(x, y, str);

        // 设置字体颜色
        dc.SetTextColor(RGB(255, 0, 0));

        CRect rect(x, y, x + w, y + size.cy);
        dc.DrawText(str, &rect, DT_LEFT);

    }

    CView::OnTimer(nIDEvent);
}
字体渐变色

7,动态图标

在资源视图中添加4个icon文件

在框架 .h 文件中添加

private:
    HICON icon[4];

构造函数中加载资源

// CMainFrame 构造/析构

CMainFrame::CMainFrame()
{
    // TODO: 在此添加成员初始化代码
    
    // 加载图片
    // 获取应用程序 AfxGetApp()
    icon[0] = AfxGetApp()->LoadIconW(IDI_ICON1);
    icon[1] = AfxGetApp()->LoadIconW(IDI_ICON2);
    icon[2] = AfxGetApp()->LoadIconW(IDI_ICON3);
    icon[3] = AfxGetApp()->LoadIconW(IDI_ICON4);
}

设置定时器

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
        !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
    {
        TRACE0("未能创建工具栏
");
        return -1;      // 未能创建
    }

    if (!m_wndStatusBar.Create(this))
    {
        TRACE0("未能创建状态栏
");
        return -1;      // 未能创建
    }
    m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

    // TODO: 如果不需要可停靠工具栏,则删除这三行
    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockControlBar(&m_wndToolBar);

    SetTimer(1, 200, NULL);

    return 0;
}

定时器处理函数

void CMainFrame::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    static int i = 0;

    // 修改标题
    SetClassLong(m_hWnd, GCL_HICON, (LONG)icon[i]);
    i++;
    if (i == 4) {
        i = 0;
    }

    CFrameWnd::OnTimer(nIDEvent);
}

https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setclasslonga

原文地址:https://www.cnblogs.com/xiangtingshen/p/10802258.html