标题:[求助]还是STATIC上显示位图的问题
只看楼主
zabbey
Rank: 1
等 级:新手上路
帖 子:55
专家分:0
注 册:2007-10-10
 问题点数:0 回复次数:8 
[求助]还是STATIC上显示位图的问题

上次问过一次:http://bbs.bc-cn.net/dispbbs.asp?boardid=55&replyid=372186&id=176725&page=1&skin=0&star=1
上次的代码在后面看过后,觉得还有问题,改了下,主要是注释掉了OnOpen()中的那个DrawBMP()
void CBmpViewDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

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
{
DrawBmp();

CDialog::OnPaint();
}
}

void CBmpViewDlg::OnOpen()
{
// TODO: Add your control notification handler code here
CFileDialog pFiledlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "位图文件(*.bmp)|*.bmp|",NULL);
if(pFiledlg.DoModal())
{
m_strFile = pFiledlg.GetPathName();
}
if(m_strFile == "")
{
//没选择文件
return;
}

//刷新
//Invalidate();

hbitmap = (HBITMAP)::LoadImage (::AfxGetInstanceHandle(), m_strFile,
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

CRect rect;
CStatic* p_bitmap = (CStatic*)GetDlgItem(IDC_IMAGE);
p_bitmap->GetClientRect(&rect);
InvalidateRect(rect, TRUE);
UpdateWindow(); //刷新时会调用OnPaint()里的DrawBmp()

//DrawBmp();

}

void CBmpViewDlg::DrawBmp()
{
CRect rect;
CStatic* p_bitmap = (CStatic*)GetDlgItem(IDC_IMAGE);
p_bitmap->GetClientRect(&rect);

CWnd *pWnd = GetDlgItem(IDC_IMAGE);
CDC *pDC = pWnd->GetDC();

BITMAP m_Bm;
HBITMAP hOldBmp;
::GetObject(hbitmap, sizeof(m_Bm), &m_Bm);

CDC dcImage;
dcImage.CreateCompatibleDC(pDC);
hOldBmp = (HBITMAP)dcImage.SelectObject(hbitmap);

int x, y;
x = (rect.right - m_Bm.bmWidth) / 2;
y = (rect.bottom - m_Bm.bmHeight) / 2;
pDC->BitBlt(x, y, x + m_Bm.bmWidth, y + m_Bm.bmHeight, &dcImage, 0, 0, SRCCOPY);

dcImage.SelectObject(hOldBmp);

}

这次发现窗口每次最小化后恢复,位图是一闪就没了.感觉上面的代码应该是没问题了,可能是我对WINDOWS刷新机制认识有问题,如何改上面的代码才能不让位图一闪就消失呢?

[此贴子已经被作者于2007-10-15 16:17:09编辑过]

搜索更多相关主题的帖子: 位图 STATIC rectangle 
2007-10-15 16:13
Janlex
Rank: 3Rank: 3
等 级:新手上路
威 望:6
帖 子:303
专家分:0
注 册:2006-9-12
得分:0 
InvalidateRect(rect, TRUE);注释掉

★★★★★欢迎光临我的博客 ★★★★★
http://www.
2007-10-15 16:38
zabbey
Rank: 1
等 级:新手上路
帖 子:55
专家分:0
注 册:2007-10-10
得分:0 
以下是引用Janlex在2007-10-15 16:38:30的发言:
InvalidateRect(rect, TRUE);注释掉

这样做后,位图打开又产生了重叠现象.


2007-10-15 16:45
Janlex
Rank: 3Rank: 3
等 级:新手上路
威 望:6
帖 子:303
专家分:0
注 册:2006-9-12
得分:0 
这次发现窗口每次最小化后恢复,位图是一闪就没了.


你这句是什么意思.能不能抓个图发上来

★★★★★欢迎光临我的博客 ★★★★★
http://www.
2007-10-15 16:52
zabbey
Rank: 1
等 级:新手上路
帖 子:55
专家分:0
注 册:2007-10-10
得分:0 
以下是引用Janlex在2007-10-15 16:52:03的发言:
这次发现窗口每次最小化后恢复,位图是一闪就没了.


你这句是什么意思.能不能抓个图发上来

抓不了啊,太快了.


2007-10-15 17:15
Janlex
Rank: 3Rank: 3
等 级:新手上路
威 望:6
帖 子:303
专家分:0
注 册:2006-9-12
得分:0 

void CBmpViewDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

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
{
DrawBmp();

CDialog::OnPaint();
}
}

void CBmpViewDlg::OnOpen()
{
// TODO: Add your control notification handler code here
CFileDialog pFiledlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "位图文件(*.bmp)|*.bmp|",NULL);
if(pFiledlg.DoModal())
{
m_strFile = pFiledlg.GetPathName();
}
if(m_strFile == "")
{
//没选择文件
return;
}

//刷新
//Invalidate();

hbitmap = (HBITMAP)::LoadImage (::AfxGetInstanceHandle(), m_strFile,
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

CRect rect;
CStatic* p_bitmap = (CStatic*)GetDlgItem(IDC_IMAGE);
p_bitmap->GetClientRect(&rect);
Invalidate();
UpdateWindow(); //刷新时会调用OnPaint()里的DrawBmp()

//DrawBmp();

}

void CBmpViewDlg::DrawBmp()
{
CPaintDC dcs(this);
CRect rect;
CStatic* p_bitmap = (CStatic*)GetDlgItem(IDC_IMAGE);
p_bitmap->GetClientRect(&rect);

CWnd *pWnd = GetDlgItem(IDC_IMAGE);
CDC *pDC = pWnd->GetDC();

BITMAP m_Bm;
HBITMAP hOldBmp;
::GetObject(hbitmap, sizeof(m_Bm), &m_Bm);

CDC dcImage;
dcImage.CreateCompatibleDC(pDC);
hOldBmp = (HBITMAP)dcImage.SelectObject(hbitmap);

int x, y;
x = (rect.right - m_Bm.bmWidth) / 2;
y = (rect.bottom - m_Bm.bmHeight) / 2;
pDC->BitBlt(x, y, x + m_Bm.bmWidth, y + m_Bm.bmHeight, &dcImage, 0, 0, SRCCOPY);

dcImage.SelectObject(hOldBmp);

}



try.我先吃饭去了


★★★★★欢迎光临我的博客 ★★★★★
http://www.
2007-10-15 17:59
zabbey
Rank: 1
等 级:新手上路
帖 子:55
专家分:0
注 册:2007-10-10
得分:0 
DrawBMP()中的
CPaintDC dcs(this);
作用是什么?

2007-10-15 18:16
Janlex
Rank: 3Rank: 3
等 级:新手上路
威 望:6
帖 子:303
专家分:0
注 册:2006-9-12
得分:0 
嘿嘿,这个就说来话长了...

CPaintDC是何物? 你看了他构造函数你就知道,他其实也是掉用了BeginPaint()的.学过SDK都知道BeginPaint()函数,会从消息队列中把所有WM_PAINT一次性读出来.

Invalidate();
UpdateWindow();
咱们再把这两个函数, 第一个是使窗口区域所有的都无效,他会放消息队列中投放一个WM_PAINT,这个WM_PAINT和一般消息一样,是正常消息,是会排列的.也就是会等到前们的消息读完后,他才会被DispatchMessage转换
UpdateWindow();就不同了, 他也会投放一个WM_PAINT消息.但UpdateWindow函数投放的是不排队的,也就是窗口函数马上会读出他.

你现在明白了吗?

当你点击Open按钮执行Open函数时,会发送两个WM_PAINT

肯定是先收到UpdateWindow()发送来的WM_PAINT, 这样会用BitBlt绘制到IDC_IMAGE上.
但马上就会收到Invalidate()发送来的WM_PAINT, 此时是窗口无效的消息. 肯定就显示不了啦.

所以我刚才代码中用到了CPaintDC dcs(this); 其实没有任何作用..只是想读出Invalidate()使窗口无效的那个WM_PAINT,这样,以后就不会使窗口无效了.

不晓得我解释的你明白不明白我,口头表达能力很差

★★★★★欢迎光临我的博客 ★★★★★
http://www.
2007-10-15 21:53
zabbey
Rank: 1
等 级:新手上路
帖 子:55
专家分:0
注 册:2007-10-10
得分:0 

在一本书上找到了一个解释:
CPaintDC用于响应窗口重绘消息(WM_PAINT)的绘图输出。CPaintDC在构造函数中调用BeginPaint()取得设备上下文,在析构函数中调用EndPaint()释放设备上下文。EndPaint()除了释放设备上下文外,还负责从消息队列中清除WM_PAINT消息。因此,在处理窗口重画时,必须使用CPaintDC,否则WM_PAINT消息无法从消息队列中清除,将引起不断的窗口重画。CPaintDC也只能用在WM_PAINT消息处理之中。


2007-10-18 22:35



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-177820-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.096975 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved