访问当前目录下的子目录和文件信息
运行该程序,可以显示当前目录下的子目录和文件信息,如同DOS的DIR命令一样。可以轻易修改以便递归访问所有子目录。(和操作系统中的FCB-文件控制块概念相关)
VC++ 6.0 WIN32 API版的操作系统生产者-消费者问题源码
我从网上下载的一个生产者-消费者的代码修改而来,并补充了注释,使得程序更加简明易懂。wait原语和signal原语对应于WIN32 API中的WaitForSingleObject函数和ReleaseSemaphore函数。使用了3个信号量,mutex、empty和full(参见西电版汤小丹“计算机操作系统”教材)。
SBA(Sparse Bundle Adjustment)的VC2010版本
本压缩包里是SBA 1.6(Sparse Bundle Adjustment)的VC2010版本
原下载地址是:http://www.ics.forth.gr/~lourakis/sba
本VC2010版本(sba.sln)是使用CMake,根据原下载源码中CMakeLists.txt转换而成,并删除一些不必要的配置/文件后精简而成.其中包含两个项目,sba和eucsbademo,这两个项目的编译和链接选项也进行了简化.
其中sba项目将生成sba.lib,是SBA核心算法的静态库.
ecusbademo项目将生成ecusbademo.exe,是SfM的演示程序.该项目用到两个静态库,一个是上边的sba.lib,一个是线性代数库clapack.lib.
SBA(VC2010版)的目录结构:
./sba SBA源码 (含readme.txt)
./demo ecusbademo源码 (含readme.txt)
./lib 静态库存放位置,包括clapack.lib和sba项目生成的sba.lib都放在这里
./documentation 相关论文和文档(我搜集下载的)
./vc2010 VC2010的解决方案和项目配置文件(*.sln, *.vcxproj...)
使用方法:
使用VC2010直接打开sba.sln,全部编译即可.
sba项目生成sba.lib,放入./lib目录中.
ecusbademo生成ecusbademo.exe,放入./demo中
运行ecusbademo.exe(其参数格式参见./demo中的readme.txt)
使用VC++6.0实现的“操作系统”课程中的生产者-消费者问题
一、原理
生产者线程:
while (true)
生产
wait(empty)
wait(mutex)
将产品放入队列
signal(mutex)
signal(full)
end while
消费者线程:
while (true)
wait(full)
wait(mutex)
从队列中取出产品
signal(mutex)
signal(empty)
消费
end while
信号量full表示可消费的产品数量,empty代表空单元的数量(用于容纳新生产的产品),mutex用于互斥地访问产品队列。wait操作对应于P原语,表示可用资源数量加快(减慢)生产,减慢(加快)消费”来随机调整生产和消费的时间,以观察生产者或消费者线程阻塞的状况。
程序在VC++6.0下编译通过。
用户模态对话框内子视图(子窗口)的预览和打印(之二)
MFC的视图打印/预览功能基于CView::OnFilePrint和CView::OnFilePrintPreview这两个函数。
如果要对用户自定义对话框(模态)内的子视图进行打印,直接调用该视图的CView::OnFilePrint即可,弹出的“选择打印机”对话框同样也是模态对话框,覆盖在用户对话框上。
如果要对用户对话框内的视图进行预览,直接调用该视图的CView::OnFilePrintPreview后,预览视图(MFC CPreviewView类实例)内虽然预览正常,但是挡住了用户对话框。由于用户对话框是模态的,导致预览视图上的“打印...”、“上一页”、“下一页”、“放大”、“缩小”、“单页/双页”和“关闭”等按钮均无法响应鼠标点击,处于“假死”状态。
解决方法:
第一个解决方法是先关闭用户对话框,再启动预览,详见http://download.csdn.net/detail/oliver_zheng/7639379
第二个解决方法仍然保持用户对话框,但是由于对话框为模态,无法利用主框架窗口CMainFrame作为预览框架,因此要另外创建并显示一个框架窗口(CFrameWnd的派生类),作为预览窗口。
另外创建的框架窗口类名为CPrintPreviewFrameWnd,其对应的单文档视图是CViewPrintPreview类,利用这些关联信息创建一个单文档模板,利用此单文档模板创建框架窗口,并在其内嵌视图(CViewPrintPreview类)中保存原主框架(CMainFrame)、用户对话框和其上需要打印的视图(CTestView)。然后基于CViewPrintPreview类启动预览和打印(具体过程详见第一个解决办法)。由于CViewPrintPreview的各个相关虚函数诸如OnPreparePrinting、OnBeginPrinting、OnPrepareDC、OnPrint和OnEndPrinting都被重载,用于调用真正需要打印的视图CTestView的各自函数,因此CViewPrintPreview实际上只是个“中介”视图,是连接预览视图(MFC CPreviewView类)和CTestView的桥梁。
当打印或者预览结束后,关闭自行创建的框架窗口CPrintPreviewFrameWnd,利用CViewPrintPreview类中实现保存的信息恢复主框架和用户对话框,恢复打印/预览前的环境。
代码(实现了第二个解决方法)在VC2010下编译通过。第一个解决方法的源码详见http://download.csdn.net/detail/oliver_zheng/7639379
用户模态对话框内子视图(子窗口)的预览和打印
MFC的视图打印/预览功能基于CView::OnFilePrint和CView::OnFilePrintPreview这两个函数
如果要对用户自定义对话框(模态)内的子视图(以下简称A视图)进行打印,直接调用A视图的CView::OnFilePrint即可,弹出的“选择打印机”对话框同样也是模态对话框,覆盖在用户对话框上。
如果要对用户对话框内的A视图进行预览,直接调用A视图的CView::OnFilePrintPreview后,预览视图(MFC CPreviewView类实例)内虽然预览正常,但是挡住了用户对话框。由于用户对话框是模态的,导致预览视图上的“打印...”、“上一页”、“下一页”、“放大”、“缩小”、“单页/双页”和“关闭”等按钮均无法响应鼠标点击,处于“假死”状态。
解决方法:
在调用A视图的CView::OnFilePrintPreview之前,先关闭用户对话框(CDialog::OnCancel),由于这时已不存在用于预览的A视图,再重新创建一个相同的视图(以下简称B视图),以B视图来启动OnFilePrintPreview进行预览。
MFC视图预览的原理是:以主框架窗口(CMainFrame)作为预览框架,隐藏原先的子视图(用CMainFrame::GetActiveView得到的那个,以下简称C视图),用CPreviewView类替换,同时创建包含“打印...”、“放大”、“关闭”等按钮的工具栏(CDialogBar类),最后将CPreviewView::m_pPreviewDC作为C视图OnDraw的CDC*参数传入,这样,虽然调用的是C视图的OnDraw函数,实际上却显示在了CPreviewView视图中,起到了“预览”的效果。在点击预览框架工具栏上的“打印...”按钮后, MFC体系将向原先的主框架(本例中和预览框架是同一个,都是CMainFrame)发送ID_FILE_PRINT的WM_COMMAND消息。在缺省的配置中,这将启动C视图的OnFilePrint,从而在打印机上打出C视图的内容。
在本例中,为了打印B视图,需要在CMainFrame中处理WM_COMMAND/ID_FILE_PRINT,加入额外的条件,来判断对按钮“打印...”的点击是来自B还是C视图的预览框架。在本例中用了一个变量CMainFrame::m_nPrintFrom。根据其取值(0或者1),分别启动B或者C视图的OnFilePrint。
使用方法:
程序示例在VC++2010上通过。主菜单项“打印预览测试”下,有两个子菜单项,“对话框用户视图的打印预览”用于B视图(画出一个圆);“单文档视图的打印预览”用于C视图(画出一个正方形),等同于“文件”主菜单项下的“打印预览(V)”。
卡拉OK歌词的滚动显示(模仿酷我音乐盒)
本来在做项目,看到酷我音乐盒的歌词显示挺有趣的,模仿做了一个不完整的。
(只有滚动显示,没有节奏显示)。
原理:
(1)定义一个派生自CStatic类的CKaraokeLyricCtrl类(歌词控件),自绘制风格
;
(2)准备一个背景位图(保存在CKaraokeLyricCtrl::m_dcBK中);
(3)设置两个计数器(ID分别为1和2),启动自绘制,1用来显示节奏(未实现,只
有框架),2用来滚动歌词;
(4)自绘制函数中,将绘制的滚动歌词和背景位图混合,然后输出到屏幕上。滚动
歌词的绘制使用GDI+的Graphics::DrawString函数,歌词文本的大小、位置、字体和
透明度均自动计算和变化,模仿酷我音乐盒的形式。
以上功能均封闭实现在CKaraokeLyricCtrl类中。该类可以直接使用(见下边的使用步骤)。
使用步骤:
(1)CKaraokeLyric::InitInstance中启动GDI+;
(2)在CKaraokeLyricView::OnInitialUpdate中,创建歌词控件
(CKaraokeLyricCtrl类),其大小和CKaraokeLyricView视图相同,即覆盖了后者;
(3)在菜单项响应中,使用CKaraokeLyricCtrl::ReadLyric读取歌词文件,再使用
CKaraokeLyricCtrl::Start即可启动歌词的滚动显示
未实现部分:(歌词的节拍显示)
虽然没有实现,但思路大致是:在后台先用另外一种颜色绘制当前突出显示的歌词(即字体最大的一行歌词),根据歌曲节奏,将还未唱出部分全部涂黑,然后和屏幕上的当前行突出歌词进行混合。
VC滚动视图(CScrollView类)的局部更新算法示例
在使用CScrollView(滚动视图)类时,不需要在其OnDraw/OnPaint中全部进行重绘;只需获取其update region,绘制落在此区域内的对象即可。这样可以提高显示效率,减少闪烁。
在拖动窗口大小时(WM_SIZE消息),update region是整个客户区;在点击或者拖放滚动条时(或者使用了CScrollView::ScrollToPositon函数),update region是相应的局部矩形(即新出现在在窗口中的部分)。不管是那种情况,可以将update region转换至“用户坐标系”,遍历用户在此坐标系中打算绘制的对象,确定哪些对象落在了update region内,以便进行重绘。这样,在CScrollView::OnDraw/OnPaint中仅需绘制少量对象即可。(非update region内的图形由Windows负责填充)
VC GDI+绘制渐灭的文字
GDI+绘制文字使用Graphics::DrawString函数,其中的brush参数可以使用透明度,通过控制该透明度(逐渐减少从而增加透明度),实现文字的透明度逐渐增加,最终融入到背景中,达到渐变消失的效果。具体实现上,设置计数器,每50ms触发一次,使用逐渐增强的透明度重新绘制相同的文本。为了减少闪烁,采用双缓冲绘制,即将文字在后台先绘制好,然后整体拷贝到屏幕(前台)上。程序示例在VC2010下编译通过。
从VC项目资源构建(自绘)弹出式菜单
从VC++项目中的菜单资源建立结构相同的自绘弹出式菜单,原理和步骤如下:
(1)CMenu::LoadMenu读入菜单资源;
(2)CImageList::Create读入工具栏位图;
(3)CMenu::CreatePopupMenu和CMenu::AppendMenu拷贝菜单资源,建立弹出式菜单。其中CMenu::AppendMenu第1个参数设置成MF_OWNERDRAW(自绘), 第四个参数设置成一个附加结构的指针,包括菜单项文字和位图索引等信息。通过这个结构,在自绘制时,可以获取对应的菜单项文字和位图位置索引,其中位图保存在第(2)步中的CImageList变量中;
(4)在对右鼠标键的响应函数里,使用CMenu::TrackPopupMenu启动显示弹出式菜单;
(5)在弹出式菜单的拥有者窗口(CxxxView)里,处理WM_MEASUREITEM消息和WM_DRAWITEM消息,分别调用CMenuEx::MeasureItem和CMenuEx::DrawItem, 分别用来定义菜单项的尺寸,对菜单项进行自绘;
(6)在自绘函数CMenuEx::DrawItem里,通过每个菜单项的附加结构lpDIS->itemData,获得其文字和位图索引,然后分别使用CDC::DrawText和CImageList::Draw,画出该菜单项的文字和位图,从而实现自绘制。
程序在VC6下编译通过。
没有处理的地方:如果菜单项状态是checked或者radio,程序没做处理。另外,弹出式菜单的激活/禁止时,不会自动触发其拥有者窗口的ON_UPDATE_COMMAND_UI宏。不过,可以处理owner窗口的WM_INITMEMUPOPUP消息(在弹出式菜单的每个子菜单弹出时,都会发出此消息),为每个子菜单项单独生成一个CCmdUI对象,调用其CCmdUI::DoUpdate函数,来手动触发ON_UPDATE_COMMAND_UI宏中对应的消息处理函数,使得菜单项能够根据应用环境进行激活和禁止。详见博客:
http://oliver.zheng.blog.163.com/blog/static/14241159520143210595266/
从VC项目的菜单资源构造弹出式菜单
读取VC项目中的菜单资源,构造一个完全相同的弹出式菜单。步骤如下:
(1)使用CMenu::LoadMenu载入在资源模板里创建的主菜单;
(2)定义空的弹出式菜单,将资源菜单项逐个拷贝过来。a.如果遇到分隔线或者菜单项,直接使用CMenu::AppendMenu复制;b.如果遇到子菜单,先创建子菜单并完成子菜单项的拷贝,然后将子菜单作为一项加入到当前的菜单中(同样使用CMenu::AppendMenu),这是个递归(调用)的过程;
(3)在CView::OnRButtonUp的处理函数中,调用CMenu::TrackPopupMenu显示弹出式菜单;
(4)在其Owner(CView)中加入ON_COMMAND宏,可以对菜单项的点击进行处理;
(5)弹出式菜单的释放(CMenu::Destroy)同样以递归的方式进行。
项目在VC6下编译通过。从菜单资源和工具栏位图中建立自绘弹出式菜单很快上载。
高斯消去法求逆矩阵的GLSL版本
我自己写的GLSL版本的使用高斯消去法求逆矩阵的算法. 在VC2008上编译通过. 需要用到下列OpenGL扩展: ARB_texture_float
ARB_texture_rectangle
EXT_framebuffer_object
ARB_draw_buffers
ARB_shader_objects
ARB_vertex_shader
ARB_fragment_shader
显卡支持上述OpenGL扩展的计算机才能正常运行该程序.
另外该程序还需要GLEW和GLUT的支持.
以下是和OpenCV的cvInvert的性能比较:
矩阵尺寸 cvInvert(毫秒) GLSL(毫秒)
-----------------------------------------
100 x 100 23 29
200 x 200 67 70
500 x 500 1,022 343
1000 x 1000 8,146 1,522
2000 x 2000 65,329 7,802
4000 x 4000 515,744 46,036
6000 x 6000 1,748,477 208,393
该算法在做6000 x 6000求逆时, 结果有问题. 尽快解决此问题后, 重新上传该代码. 4000 x 4000以内结果均正常.
高斯消去法求逆矩阵的GLSL版本
我自己写的GLSL版本的使用高斯消去法求逆矩阵的算法. 在VC2008上编译通过. 需要用到下列OpenGL扩展: ARB_texture_float
ARB_texture_rectangle
EXT_framebuffer_object
ARB_draw_buffers
ARB_shader_objects
ARB_vertex_shader
ARB_fragment_shader
显卡支持上述OpenGL扩展的计算机才能正常运行该程序.
另外该程序还需要GLEW和GLUT的支持.
以下是和OpenCV的cvInvert的性能比较:
矩阵尺寸 cvInvert(毫秒) GLSL(毫秒)
-----------------------------------------
100 x 100 23 29
200 x 200 67 70
500 x 500 1,022 343
1000 x 1000 8,146 1,522
2000 x 2000 65,329 7,802
4000 x 4000 515,744 46,036
6000 x 6000 1,748,477 208,393
该算法在做6000 x 6000求逆时, 结果有问题. 尽快解决此问题后, 重新上传该代码. 其它结果均正常.