帮网友改一分程序,看了代码,大致就是让一个窗体自动地从椭圆变成圆,再从圆变为椭圆。
他设置了一个定时器,在定时器里每次会改变椭圆的长径,然后创建HRGN,设置HRGN。在OnPaint里,他对椭圆进行一些渲染工作。
当他在OnTimer里,SetWindowRgn((HRGN)m_Rgn,TRUE);时,一切都没有问题。
当改为SetWindowRgn((HRGN)m_Rgn,FALSE); OnPaint(); 显式调用重新绘制的函数时,窗体却不再改变大小了~~
从二者的区别来看,首先,那个设置的区域肯定是在变化的,不然第一种情况就成功不了;其次, 经过我跟踪,OnPaint里的渲染代码是执行了的。
那么,这个问题到底出在哪里?
他设置了一个定时器,在定时器里每次会改变椭圆的长径,然后创建HRGN,设置HRGN。在OnPaint里,他对椭圆进行一些渲染工作。
当他在OnTimer里,SetWindowRgn((HRGN)m_Rgn,TRUE);时,一切都没有问题。
当改为SetWindowRgn((HRGN)m_Rgn,FALSE); OnPaint(); 显式调用重新绘制的函数时,窗体却不再改变大小了~~
从二者的区别来看,首先,那个设置的区域肯定是在变化的,不然第一种情况就成功不了;其次, 经过我跟踪,OnPaint里的渲染代码是执行了的。
那么,这个问题到底出在哪里?
解决方案 »
- MFC+OpenGL模型内存动态释放问题
- 我变了个动态库,标准c的,结果在MFC中用说无法定位程序入口点,怎么回事?
- 利用ADO,使VC++与SqlServer2000连接,总是数据库访问失败,求解决。
- 视图上放置对话框
- #######继续送分问 select的问题 谢谢大家#######
- 求教,怎么作一个按钮,按下去能让windows关机和重起的啊?
- 如何在一个DLL中建一个控件
- 先祝大家5.1快乐了,还是图象处理问题?
- 数据交换机程序开发tcp,epoll
- WinSock中sockaddr_in里面的S_un_w和S_un_b应该怎么用
- 类型转换
- 如何更改单文档窗口的底色?我生成了一个单文档程序,一运行,它的底色是白色的很刺眼!
// distortDlg.cpp : implementation file
//#include "stdafx.h"
#include "distort.h"
#include "distortDlg.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endifvoid ShowMsg(HWND hWnd=NULL,CString msg="No Message!");
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog
{
public:
CAboutDlg();// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA // ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CDistortDlg dialogCDistortDlg::CDistortDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDistortDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CDistortDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CDistortDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDistortDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}BEGIN_MESSAGE_MAP(CDistortDlg, CDialog)
//{{AFX_MSG_MAP(CDistortDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_NCHITTEST()
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CDistortDlg message handlers/*
修改OnInitDialog函数建立一个椭圆区域
并调用SetWindowRgn将该区域分配给窗口
*/
// 定义定时器事件号
#define EVENT_REDRAW 0
BOOL CDistortDlg::OnInitDialog()
{
CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here // 获得对话框的尺寸
GetClientRect(m_rectWnd);
// 创建窗体区域并与窗体建立联系
m_rgn.CreateEllipticRgn(0,0,m_rectWnd.right,m_rectWnd.bottom);
SetWindowRgn((HRGN)m_rgn,TRUE); // 设置重画窗口的定时器
this->SetTimer(EVENT_REDRAW,500,NULL);
return TRUE; // return TRUE unless you set the focus to a control
}void CDistortDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework./*
通过建立区域和调用SetWindowRgn,
已经建立一个不规则形状的窗口,
下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体
void CDistortDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
if (IsIconic())
{
SendMessage(WM_ICONERASEBKGND,(WPARAM)dc.GetSafeHdc(),0); // Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else {
//AfxMessageBox("Draw ellipse");
// 绘制一个不带边界的椭圆
dc.SelectStockObject(NULL_PEN); // 获得窗口客户区的尺寸
CRect rect;
GetClientRect(rect);
//////////////////////////////////////
//////////////////////////////////////
CBrush *pBrushOld; // 绘图设备所使用的“旧”画刷
CBrush brush; // 用来绘制椭圆的画刷 // 定义画刷
brush.CreateSolidBrush(RGB(0,0,255));
// 选取画刷作为画图设备
pBrushOld = dc.SelectObject(&brush);
// 绘制椭圆
dc.Ellipse(rect);
// 将画刷还原,并释放所用的画刷
dc.SelectObject(pBrushOld);
brush.DeleteObject();
}
}// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CDistortDlg::OnQueryDragIcon()
{
return (HCURSOR)m_hIcon;
}/*
实现窗体的任意拖动
*/
UINT CDistortDlg::OnNcHitTest(CPoint point)
{
// TODO: Add your message handler code here and/or call default // 用户点击窗口任何地方时也能拖动窗口
UINT nHitTest = CDialog :: OnNcHitTest(point) ;
return (nHitTest == HTCLIENT) ? HTCAPTION : nHitTest ;
}// 定义椭圆长轴变化的倍数
#define MULTI 1.035/*
定时时刻到了后,重新设置窗体区域
*/void CDistortDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
static nCount = 0; // 窗体变化次数计数
static bOrder = 1; // 确定窗体是变大还是变小
static double dMulti = 1; // 窗体的变化倍数
CRect rectWnd;
CPoint ptMiddle,ptTopLeft,ptBtmRight;
ptMiddle = m_rectWnd.CenterPoint(); // 确定窗体区域中心
switch(nIDEvent) // 分情况处理各种定时器事件
{
case EVENT_REDRAW: // 是重绘窗体定时器事件
nCount++;
if (bOrder == 1) // bOrder为1表示窗体变大
dMulti *= MULTI;
else
dMulti /= MULTI; // 确定窗体所在区域的矩形大小
ptTopLeft.x = ptMiddle.x - m_rectWnd.Width() / (2 * dMulti);
ptTopLeft.y = ptMiddle.y - m_rectWnd.Height() / 2;
ptBtmRight.x = ptMiddle.x + m_rectWnd.Width() / (2 * dMulti);
ptBtmRight.y = ptMiddle.y + m_rectWnd.Height() / 2;
rectWnd.SetRect(ptTopLeft,ptBtmRight);
m_rgn.Detach(); // 释放区域对象,为下次创建作准备
// 根据前面确定的矩形创建椭圆区域
m_rgn.CreateEllipticRgn(ptTopLeft.x,ptTopLeft.y,ptBtmRight.x,ptBtmRight.y);
// 将窗体限制在该区域内,第二个参数取TRUE表示要重绘窗体
//if(SetWindowRgn((HRGN)m_rgn,TRUE))
//AfxMessageBox("Ko Ko");
CString msg;
msg.Format("left:%d top:%d right:%d bottom:%d", ptTopLeft.x,ptTopLeft.y,ptBtmRight.x,ptBtmRight.y);
ShowMsg(NULL,msg);
SetWindowRgn((HRGN)m_rgn,FALSE);
//SetWindowRgn((HRGN)m_rgn,TRUE);
//OnPaint();
if (nCount == 10) // 若已经经过了10此变化,则反向变化
{
nCount = 0;
bOrder = (bOrder == 1) ? -1 : 1;
}
break;
}
CDialog::OnTimer(nIDEvent);
}void CDistortDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
}void CDistortDlg::zgc()
{ AfxMessageBox("CDistortDlg::zgc was called");
CPaintDC dc(this);
dc.SelectStockObject(NULL_PEN); // 获得窗口客户区的尺寸
CRect rect;
GetClientRect(rect); CBrush *pBrushOld; // 绘图设备所使用的“旧”画刷
CBrush brush; // 用来绘制椭圆的画刷 // 定义画刷
brush.CreateSolidBrush(RGB(0,0,255));
// 选取画刷作为画图设备
pBrushOld = dc.SelectObject(&brush);
// 绘制椭圆
dc.Ellipse(rect);
// 将画刷还原,并释放所用的画刷
dc.SelectObject(pBrushOld);
brush.DeleteObject();
}
void ShowMsg(HWND hWnd,CString msg)
{
static bool bFirst=true; if(bFirst)
{
srand(GetTickCount());
bFirst=false;
}
HDC hdc=GetDC(hWnd);
HPEN hpen=CreatePen(PS_SOLID,100,RGB(255,255,255));
SelectObject(hdc,hpen);
MoveToEx(hdc,0,0,NULL);
LineTo(hdc,180,0);
SetTextColor(hdc,RGB(0,0,0));
SetBkMode(hdc,TRANSPARENT);
TextOut(hdc,0,0,msg,strlen(msg));
DeleteObject(hpen);
ReleaseDC(hWnd,hdc);
}