热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

菜虫的悲哀:搞不懂,编译链接均通过,一运行就关不掉,只好用任务管理器强关,结果导致CMyBitmapView的源程序打不开,到底是啥原因?

还是那个只能打开并显示任意的系统磁盘上的24位真彩bmp文件的问题,常规方法咱看不懂,什么文件头,什么信息头,什么句柄,什么参数表,一看头就晕.虽说CBitmap类只能显示VCMFC所生成的应用程序
还是那个只能打开并显示任意的系统磁盘上的24位真彩bmp文件的问题,常规方法咱看不懂,什么文件头,什么信息头,什么句柄,什么参数表,一看头就晕.虽说CBitmap类只能显示VC/MFC所生成的应用程序中资源的bmp文件,但是我仅仅把bitmap.LoadBitmap(dlg.GetFileName())加入程序,编译/链接/运行均没问题,我想再通过适当扩展一下,应该能够达到设计目的.只是,如此尝试的结果却是......
此GUI是基于文档/视图类的SDI:
手动添加部分:
void CMyBitmapDoc::OnFileOpen() 
{
// TODO: Add your command handler code here
CFileDialog dlg(TRUE, _T(".bmp"), NULL, OFN_FILEMUSTEXIST,
_T("位图文件(*.bmp)|*.bmp||"));
if(dlg.DoModal() == IDOK)
{
    dlg.GetPathName();//设定只能打开(位图文件(*.bmp))的模态对话框
CBitmap::operator HBITMAP;//如果调用成功的话,用CBitmap类中的bitmap对象代替 win32操作系统中的处理GDI接口的句柄(不知对否?)

CBitmap bitmap;
//bitmap.LoadBitmap(dlg.GetFileName());照着人家网上搬了一句,不知它能否成功装载系统磁盘上的DIB类型的bmp文件进入bitmap对象?

CDC MemDC;
MemDC.SelectObject(bitmap);//映射bmp图像文件到内存
//创建内存与系统显示兼容的设备上下文
MemDC.CreateCompatibleDC(NULL);

BITMAP bm;
bitmap.GetBitmap (&bm);
int bmWidth=bm.bmWidth,bmHeight=bm.bmHeight;//获得位图文件的宽/高信息
CRect rect;
rect.SetRect(0,0,bmWidth,bmHeight);
CWnd currentwindow;
currentwindow.GetClientRect(rect);//在当前视图窗口客户区创建一个与位图一样大小的显示文件的矩形窗
MemDC.StretchBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,
bmWidth,bmHeight,SRCCOPY);//位图可伸缩的从源设备上下文映射到目的设备上下文
return;
}
}
然后再在CBitmapView::OnDraw(CDC*pDC)(由于我已经打不开了,MFC自动生成的源代码就不COPY了)反正,就是在最后的添加代码处添了一句使无效函数:Invalidate();//立即显示位图
问题疹状如下:
1/ 编译虽没问题,但编译后马上会出现系统错误:"windows-延缓写入失败:windows无法为VC/MFC的SDI应用程序所在目录(F:\C++programs\MyBitmap\MyBitmap\MyBitmap.plg)文件保存所有数据.数据已经丢失.这个错误可能是由于您的计算机硬件或网络连接的失败而造成的.请尝试把这份文件保存到别处.
2/ 下面是调试报告:
--------------------Configuration: MyBitmap - Win32 Debug--------------------
Linking...
LINK : LNK6004: Debug/MyBitmap.exe not found or not built by the last incremental link; performing full link
.\Debug\MyBitmapView.obj : error : Internal error during ReadSymbolTable
  ExceptionCode            = C0000006
  ExceptionFlags           = 00000000
  ExceptionAddress         = 0040C842
  NumberParameters         = 00000003
  ExceptionInformation[ 0] = 00000000
  ExceptionInformation[ 1] = 00B70000
  ExceptionInformation[ 2] = C0000185
CONTEXT:
  Eax    = 00000008  Esp    = 0012F704
  Ebx    = 003796D0  Ebp    = 00000008
  Ecx    = 00000002  Esi    = 00B70000
  Edx    = 00000008  Edi    = 0012F730
  Eip    = 0040C842  EFlags = 00010202
  SegCs  = 0000001B  SegDs  = 00000023
  SegSs  = 00000023  SegEs  = 00000023
  SegFs  = 0000003B  SegGs  = 00000000
  Dr0    = 0012F704  Dr3    = 003796D0
  Dr1    = 00000008  Dr6    = 00000002
  Dr2    = 00000000  Dr7    = 00000000
Error executing link.exe.
Tool execution canceled by user.
3/ 一点"运行"按钮,就出现了计算机开机就死的那种黑屏(蓝屏)的等待C命令提示符界面.
如果要想打开CMyBitmapView源文件,若要从ClassView打开,鼠标处于等待状态一段长时间后,又回到光标状态,但界面并没有替换;若从FileView打开,疹状同上;外加一个系统错误报告对话框:"在对一未命名文件进行访问时发生了一个不明错误.

9 个解决方案

#1


更倒霉的是,下午关机时,屏幕中央出现一“正在关断网络连接”系统窗口,稍后此窗口区域黑屏,自动关机关不了,只好硬关机。晚上开机,系统报告“因以下文件的损坏或者丢失,windows无法启动\system32\hal.dll,请重新安装以上文件的拷贝。本想拿个系统安装盘修复一下,谁知给我来了个重新安装。前几天我的系统由于中标(中毒)了,刚装过。唉,程序又搞不出来,系统又老崩溃,最近真是“走运”啊?!hal.dll:Hardware Abstraction Layer dynamic link library:硬件抽象层链接库,到底是啥原因导致其损坏或丢失的?难不成是俺的编程误操作?

#2


虽然上述问题至今还没搞明白,但bmp的显示我总算蒙出来了,虽然不尽如人意,但总算告一段落了,虽然一次显示不全(甚至不显示),但最小化后,再恢复原大小,bmp原貌尽现:
引入24位CDib类,
头文件定义如下:
// DIB.h

#ifndef __DIB_H__
#define __DIB_H__

class CDib
{

public:
CDib();
~CDib();

BOOL Load( const char * );
BOOL Save( const char * );
BOOL Draw( CDC *, int nX = 0, int nY = 0, int nWidth = -1, int nHeight = -1 );
BOOL SetPalette( CDC * );

private:
CPalette m_Palette;
unsigned char *m_pDib, *m_pDibBits;
DWORD m_dwDibSize;
BITMAPINFOHEADER *m_pBIH;
RGBQUAD *m_pPalette;
int m_nPaletteEntries;

};

#endif
源文件实现如下:
// DIB.cpp

#include "stdafx.h"
#include "DIB.h"

CDib::CDib()
{

// Set the Dib pointer to
// NULL so we know if it's
// been loaded.
m_pDib = NULL;

}

CDib::~CDib()
{

// If a Dib has been loaded,
// delete the memory.
if( m_pDib != NULL )
delete [] m_pDib;

}

BOOL CDib::Load( const char *pszFilename )
{

CFile cf;

// Attempt to open the Dib file for reading.
if( !cf.Open( pszFilename, CFile::modeRead ) )
return( FALSE );

// Get the size of the file and store
// in a local variable. Subtract the
// size of the BITMAPFILEHEADER structure
// since we won't keep that in memory.
DWORD dwDibSize;
dwDibSize =
cf.GetLength() - sizeof( BITMAPFILEHEADER );

// Attempt to allocate the Dib memory.
unsigned char *pDib;
pDib = new unsigned char [dwDibSize];
if( pDib == NULL )
return( FALSE );

BITMAPFILEHEADER BFH;

// Read in the Dib header and data.
try{

// Did we read in the entire BITMAPFILEHEADER?
if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) )
!= sizeof( BITMAPFILEHEADER ) ||

// Is the type 'MB'?
BFH.bfType != 'MB' ||

// Did we read in the remaining data?
cf.Read( pDib, dwDibSize ) != dwDibSize ){

// Delete the memory if we had any
// errors and return FALSE.
delete [] pDib;
return( FALSE );
}
}

// If we catch an exception, delete the
// exception, the temporary Dib memory,
// and return FALSE.
catch( CFileException *e ){
e->Delete();
delete [] pDib;
return( FALSE );
}

// If we got to this point, the Dib has been
// loaded. If a Dib was already loaded into
// this class, we must now delete it.
if( m_pDib != NULL )
delete m_pDib;

// Store the local Dib data pointer and
// Dib size variables in the class member
// variables.
m_pDib = pDib;
m_dwDibSize = dwDibSize;

// Pointer our BITMAPINFOHEADER and RGBQUAD
// variables to the correct place in the Dib data.
m_pBIH = (BITMAPINFOHEADER *) m_pDib;
m_pPalette =
(RGBQUAD *) &m_pDib[sizeof(BITMAPINFOHEADER)];

// Calculate the number of palette entries.
m_nPaletteEntries = 1 << m_pBIH->biBitCount;
if( m_pBIH->biBitCount > 8 )
m_nPaletteEntries = 0;
else if( m_pBIH->biClrUsed != 0 )
m_nPaletteEntries = m_pBIH->biClrUsed;

// Point m_pDibBits to the actual Dib bits data.
m_pDibBits =
&m_pDib[sizeof(BITMAPINFOHEADER)+
m_nPaletteEntries*sizeof(RGBQUAD)];

// If we have a valid palette, delete it.
if( m_Palette.GetSafeHandle() != NULL )
m_Palette.DeleteObject();

// If there are palette entries, we'll need
// to create a LOGPALETTE then create the
// CPalette palette.
if( m_nPaletteEntries != 0 ){

// Allocate the LOGPALETTE structure.
LOGPALETTE *pLogPal = (LOGPALETTE *) new char
[sizeof(LOGPALETTE)+
m_nPaletteEntries*sizeof(PALETTEENTRY)];

if( pLogPal != NULL ){

// Set the LOGPALETTE to version 0x300
// and store the number of palette
// entries.
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = m_nPaletteEntries;

// Store the RGB values into each
// PALETTEENTRY element.
for( int i=0; i pLogPal->palPalEntry[i].peRed =
m_pPalette[i].rgbRed;
pLogPal->palPalEntry[i].peGreen =
m_pPalette[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue =
m_pPalette[i].rgbBlue;
}

// Create the CPalette object and
// delete the LOGPALETTE memory.
m_Palette.CreatePalette( pLogPal );
delete [] pLogPal;
}
}

return( TRUE );

}

BOOL CDib::Save( const char *pszFilename )
{

// If we have no data, we can't save.
if( m_pDib == NULL )
return( FALSE );

CFile cf;

// Attempt to create the file.
if( !cf.Open( pszFilename,
CFile::modeCreate | CFile::modeWrite ) )
return( FALSE );

// Write the data.
try{

// First, create a BITMAPFILEHEADER
// with the correct data.
BITMAPFILEHEADER BFH;
memset( &BFH, 0, sizeof( BITMAPFILEHEADER ) );
BFH.bfType = 'MB';
BFH.bfSize = sizeof( BITMAPFILEHEADER ) + m_dwDibSize;
BFH.bfOffBits = sizeof( BITMAPFILEHEADER ) +
sizeof( BITMAPINFOHEADER ) +
m_nPaletteEntries * sizeof( RGBQUAD );

// Write the BITMAPFILEHEADER and the
// Dib data.
cf.Write( &BFH, sizeof( BITMAPFILEHEADER ) );
cf.Write( m_pDib, m_dwDibSize );
}

// If we get an exception, delete the exception and
// return FALSE.
catch( CFileException *e ){
e->Delete();
return( FALSE );
}

return( TRUE );

}

BOOL CDib::Draw( CDC *pDC, int nX, int nY, int nWidth, int nHeight )
{

// If we have not data we can't draw.
if( m_pDib == NULL )
return( FALSE );

// Check for the default values of -1
// in the width and height arguments. If
// we find -1 in either, we'll set them
// to the value that's in the BITMAPINFOHEADER.
if( nWidth == -1 )
nWidth = m_pBIH->biWidth;
if( nHeight == -1 )
nHeight = m_pBIH->biHeight;

// Use StretchDIBits to draw the Dib.
StretchDIBits( pDC->m_hDC, nX, nY,
nWidth, nHeight,
0, 0,
m_pBIH->biWidth, m_pBIH->biHeight,
m_pDibBits,
(BITMAPINFO *) m_pBIH,
BI_RGB, SRCCOPY );

return( TRUE );

}

BOOL CDib::SetPalette( CDC *pDC )
{

// If we have not data we
// won't want to set the palette.
if( m_pDib == NULL )
return( FALSE );

// Check to see if we have a palette
// handle. For Dibs greater than 8 bits,
// this will be NULL.
if( m_Palette.GetSafeHandle() == NULL )
return( TRUE );

// Select the palette, realize the palette,
// then finally restore the old palette.
CPalette *pOldPalette;
pOldPalette = pDC->SelectPalette( &m_Palette, FALSE );
pDC->RealizePalette();
pDC->SelectPalette( pOldPalette, FALSE );

return( TRUE );

}
在别人指点下,在CVCBitmapDoc.h中定义全局公有变量:CDib mydibfilename;
void CVCBitmapDoc::OnFileOpen() 
{
// TODO: Add your command handler code here
CFileDialog dlg(TRUE, _T(".bmp"), NULL, OFN_FILEMUSTEXIST,
_T("位图文件(*.bmp)|*.bmp||"));
CString bitmapfilename;
if(dlg.DoModal() == IDOK)//利用模态对话框打开bmp/dib位图文件
{
CString mydibfilename; 
        mydibfilename=dlg.GetPathName();
mydibfilename=mydib.Load(mydibfilename);
mydib.Save(mydibfilename);
}
}
。。。。。。
void CVCBitmapView::OnDraw(CDC* pDC)
{
CVCBitmapDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDoc->mydib.Draw(pDC,0,0,-1,-1);

}
到现在我才知道,为什么必须在CView类里显示bmp,如在CDoc类显示,必须要动态绑定pDoc与pDC,估计比较难,向我这样的菜虫,基础的都不会,何来技术可言?我原来也试过在CView类里显示,但指向得到文档的指针pDoc没有指向响应OnDraw()消息的Draw(),所以我一直在混混沌沌,终于20天以后,搞到一个好类,让我差不多可以蒙混过关了——真是”踏破铁鞋无觅处,得来全不费功夫!”不过,就算这样,还是出我最开始说的问题,各位师兄、师姐,如有时间帮忙搞搞。我的邮箱是:hwzcjxhl@126.com.




#3


不能给自己分,看样子此贴结不了了,关于上述问题,算了,我就在这里热情地等待回复好了!

#4


有了这个dib类还有什么问题?

#5


问题还大着呢,第一次打开bmp,要么不显示,要么显示不全,非要最小化后再还原窗口,才显示的出来。

#6


佩服楼主的研究精神, 如果是我遇到这类问题最先的方法就是从网上找现成的代码直接移到自己的工程里用. 如果一条不通就再找另一条, 这类显示图片的代码应该还是不少的.

#7


BMP文件的格式应该属于最简单的了,楼主确实可以深究一下
我没仔细看您的代码,不过我有点怀疑是否是调色板出错了,检查一下相关部分?

#8


程序流程有问题
你是想在那里显示?

在void CVCBitmapDoc::OnFileOpen() 
里面你只要记录bmp文件名,然后在view里面对这个文件操作

看你的样子好象是只操作bmp文件,那就没有必要用cdib类

使用LoadImage从文件名得到bmp图的handle
创建内存dc选入这个handle,然后使用bitblt画出来

#9


原来如此,只须在 pDoc->mydib.Draw(pDC,0,0,-1,-1);之后加上 this->Invalidate(false);//立即显示即可,理论依据:参见MSDN中关于 this->Invalidate()函数的描述:CWnd::Invalidate
void Invalidate( BOOL bErase = TRUE );

Parameters

bErase

Specifies whether the background within the update region is to be erased.

Remarks

Invalidates the entire client area of CWnd. The client area is marked for painting when the next WM_PAINT message occurs. The region can also be validated before a WM_PAINT message occurs by the ValidateRect or ValidateRgn member function.

The bErase parameter specifies whether the background within the update area is to be erased when the update region is processed. If bErase is TRUE, the background is erased when the BeginPaint member function is called; if bErase is FALSE, the background remains unchanged. If bErase is TRUE for any part of the update region, the background in the entire region, not just in the given part, is erased. 

Windows sends a WM_PAINT message whenever the CWnd update region is not empty and there are no other messages in the application queue for that window.

老实说,老师给我们讲过程序设计流程,思路就类似我搬的CDib类,原来我太沉醉于CBitmap及CBitmapFile类了,前者根本不可能直接显示位图,后者到现在我还没搞懂,所以就找了一个我比较容易掌握的简单的类来辅助设计!不过,Thank everyone of you all the same!

推荐阅读
  • 转载:MFC 获得各类指针、句柄的方法
    2019独角兽企业重金招聘Python工程师标准转载:最近有些人在问MFC编程一些要点,有一些句柄的获取、指针的获取是 ... [详细]
  • 颜色迁移(reinhard VS welsh)
    不要谈什么天分,运气,你需要的是一个截稿日,以及一个不交稿就能打爆你狗头的人,然后你就会被自己的才华吓到。------ ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • C#路径,文件,目录,IO常见问题汇总主要内容:一、路径的相关操作,如判定路径是否合法,路径类型, ... [详细]
  • 本博客基于android7.1版本分析,仅用于沟通学习使用上一篇博客介绍了android导出vCard联系人流程紧接着我们在这篇博客来看看它是如何导入一个vCard ... [详细]
  • Android中Bitmap与Drawable的区别有哪些?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 本文介绍了Linux Shell中括号和整数扩展的使用方法,包括命令组、命令替换、初始化数组以及算术表达式和逻辑判断的相关内容。括号中的命令将会在新开的子shell中顺序执行,括号中的变量不能被脚本余下的部分使用。命令替换可以用于将命令的标准输出作为另一个命令的输入。括号中的运算符和表达式符合C语言运算规则,可以用在整数扩展中进行算术计算和逻辑判断。 ... [详细]
  • 设计模式——模板方法模式的应用和优缺点
    本文介绍了设计模式中的模板方法模式,包括其定义、应用、优点、缺点和使用场景。模板方法模式是一种基于继承的代码复用技术,通过将复杂流程的实现步骤封装在基本方法中,并在抽象父类中定义模板方法的执行次序,子类可以覆盖某些步骤,实现相同的算法框架的不同功能。该模式在软件开发中具有广泛的应用价值。 ... [详细]
  • 本文介绍了如何在Azure应用服务实例上获取.NetCore 3.0+的支持。作者分享了自己在将代码升级为使用.NET Core 3.0时遇到的问题,并提供了解决方法。文章还介绍了在部署过程中使用Kudu构建的方法,并指出了可能出现的错误。此外,还介绍了开发者应用服务计划和免费产品应用服务计划在不同地区的运行情况。最后,文章指出了当前的.NET SDK不支持目标为.NET Core 3.0的问题,并提供了解决方案。 ... [详细]
  • Android源码中的Builder模式及其作用
    本文主要解释了什么是Builder模式以及其作用,并结合Android源码来分析Builder模式的实现。Builder模式是将产品的设计、表示和构建进行分离,通过引入建造者角色,简化了构建复杂产品的流程,并且使得产品的构建可以灵活适应变化。使用Builder模式可以解决开发者需要关注产品表示和构建步骤的问题,并且当构建流程发生变化时,无需修改代码即可适配新的构建流程。 ... [详细]
  • 本文介绍了iOS开发中检测和解决内存泄漏的方法,包括静态分析、使用instruments检查内存泄漏以及代码测试等。同时还介绍了最能挣钱的行业,包括互联网行业、娱乐行业、教育行业、智能行业和老年服务行业,并提供了选行业的技巧。 ... [详细]
  • 从具有确切位置的两个imageView创建位图 - Create bitmap from two imageView with exact location
    MyTarget:Getonephotofromcameraorgallery,thensetittoimageViewA从相机或图库中获取一张照片,然后将其设置 ... [详细]
author-avatar
谢莹UiK_1928
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有