按日归档: 2007/04/09

VC小技巧15则

一、 一次只运行一个程序实例
下列两种方式都可以实现,建议采用第二种方式:
1、 if( FindWindow(NULL,"程序标题"))
         exit(0);
2、BOOL CDemoTBarEApp::InstanceIsRun()
{
HANDLE m_hMutex;
m_hMutex = ::CreateMutex(NULL, TRUE, _T("YourApplication"));
ASSERT(m_hMutex);
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
m_hMutex = NULL;
return TRUE;//实例已经运行
}
return FALSE;//实例未运行
}

二、 装载光标
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
其中::SetCursor()是全局函数,用来设置整个例程的光标参数是宏定义光标句柄。AfxGetApp ()是一个系统函数,它返回当前的一个CWinApp对象。其成员函数LoadStandardCursor()用来读取一个系统指针,每一种系统指针的具体宏定义如下:
IDC_APPSTARTING 带小沙漏的标准箭头
IDC_ARROW 标准箭头
IDC_CROSS 十字光标(用于定位)
IDC_HAND Windows 2000:手型
IDC_HELP 带问号的箭头
IDC_IBEAM I型标
IDC_ICON Obsolete for applications marked version 4.0 or later.
IDC_NO   禁止符号
IDC_SIZE Obsolete for applications marked version 4.0 or later. Use IDC_SIZEALL.
IDC_SIZEALL 十字箭头
IDC_SIZENESW 指向东北和西南的双向箭头
IDC_SIZENS 指向南和北的双向箭头
IDC_SIZENWSE 指向西北和东南的双向箭头
IDC_SIZEWE 指向东西的双向箭头
IDC_UPARROW 上箭头
IDC_WAIT 沙漏

三、获得主框架:
CMainFrame * pMainframe = (CMainFrame *) AfxGetApp()->m_pMainWnd;
.获取应用程序的实例句柄:
      Example: HANDLE hInstance=AfxGetInstanceHandle();

获得应用程序主窗口的指针:
      Example: AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED); //使程序最大化

四、重新建立字体的代码
if(m_fontLogo.m_hObject)
m_fontLogo.Detach();

m_fontLogo.CreateFont(nHeight, 0, 0, 0, nWeight, bItalic, bUnderline,0,0,0,0,0,0, Name);

五、用指定颜色填充区域
dc.FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE));

六、绘制立体字体效果的字体,很值得一看
void CTestView::OnPaint()
{
CPaintDC dc(this); // device context for painting

CRect rect;
GetWindowRect(rect);

CFont m_fontLogo;
m_fontLogo.CreateFont(24, 0, 0, 0, FW_BOLD, true,
FALSE,0,0,0,0,0,0, "Arial");
CString m_LogoText;
m_LogoText=_T("Benlux Pro3D System");
dc.SetBkMode(TRANSPARENT);

CFont * OldFont = dc.SelectObject(&m_fontLogo);

// draw text in DC
COLORREF OldColor = dc.SetTextColor( ::GetSysColor( COLOR_3DHILIGHT));

rect.right = rect.Width();
rect.bottom = rect.Height();
rect.left = rect.top = 0;
dc.FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE));

dc.DrawText( m_LogoText, rect + CPoint(1,1), DT_SINGLELINE | DT_LEFT | DT_VCENTER);
dc.SetTextColor( ::GetSysColor( COLOR_3DSHADOW));
dc.DrawText( m_LogoText, rect, DT_SINGLELINE | DT_LEFT | DT_VCENTER);

// restore old text color
dc.SetTextColor( OldColor);
// restore old font
dc.SelectObject(OldFont);
// Do not call CView::OnPaint() for painting messages
}

七、简单的消息检索和抽取函数,能够让系统响应其它操作
BOOL PeekAndPump()
{
static MSG msg;

while (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) {
if (!AfxGetApp()->PumpMessage()) {
   ::PostQuitMessage(0);
   return FALSE;
}
}
return TRUE;
}

八、在你的程序中用动画光标替换默认的等待光标 (ANI光标的使用)
HCURSOR m_hAniCursor=NULL;
BeginWaitCursor();   //begin wait cursor for api function

//load ani cursor from file in current path
TCHAR cursorPath[MAX_PATH]; GetModuleFileName(NULL,cursorPath,MAX_PATH);
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath(cursorPath, drive, dir, fname, ext );
sprintf(cursorPath,"%s%swait.ani",drive,dir); //ani cursor file name is wait.ani

m_hAniCursor= LoadCursorFromFile(cursorPath);
HCURSOR oldCursor;
if(m_hAniCursor != NULL)
oldCursor=SetCursor(m_hAniCursor);

for(long i=0;i<1000;i++)
Sleep(5);

oldCursor=NULL;
m_hAniCursor=NULL;
EndWaitCursor(); //end wait cursor for api function

九、如何限制编辑框中的准许字符
     如果用户在编辑控件中只允许接收数字,可以使用一个标准的编辑控件并指
定新的创建标志ES_NUMBERS,它是Windows 95新增加的标志,该标志限制 编辑控
件只按收数字字符。
如果用户需要复杂的编辑控件,可以使用Microsoft 的屏蔽编辑控件,它是一个很有用的OLE定制控件。
    如果希望不使用OLE 定制控件自己处理字符,可以派生一个CEdit 类并处理WM_CHAR消息,然后从编辑控件中过滤出特定的字符。首先,使用ClassWizard 建立一个 CEdit的派生类,其次,在对话类中指定一个成员变量将编辑控件分类在OnInitdialog 中调用CWnd: : SubclassDlgItem .

//In your dialog class declaration (.H file )
private :
    CMyEdit m_wndEdit ; // Instance of your new edit control .

//In you dialog class implementation (.CPP file )
BOOL CSampleDialog : : OnInitDialog ( )
{

    //Subclass the edit lontrod .
    m_wndEdit .SubclassDlgItem (IDC_EDIT,this );
    …
}
    使用ClassWizard处理WM_CHAR消息,计算nChar参量并决定所执行的操作,用户可以确定是否修改、传送字符。下例说明了如何显示字母字符,如果字符是字母字符,则调用CWnd ; OnChar,否则不调用OnChar.
//Only display alphabetic dharacters .
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UITN nFlags )
{
    //Determine if nChar is an alphabetic character .
    if (: : IsCharAlpha ( ( TCHAR) nChar ) )
        CEdit : : OnChar (nChar, nRepCnt , nFlags );
}
    如果要修改字符,则不能仅仅简单地用修改过的nChar调用CEdit : : OnChar。要修改一个字符,需要首先修改nChar,然后用修改过的nChar调用CWnd: : DefWindowProc。下例说明了如何将字符转变为大写:
//Make all characters uppercase
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UINT nFlags )
{
    //Make sure character is uppercase .
    if (: : IsCharAlpha ( .( TCHAR) nChar)
         nChar=: : CharUpper (nChar ) ;
    //Bypass default OnChar processing and directly call default window proc.
    DefWindProc (WM_CHAR, nChar , MAKELPARAM (nRepCnt , nFlags )) ;
}

十、串太长时如何在其末尾显示一个省略号
    调用CDC:: DrawText并指定DT_END_ELLIPSIS标志,这样就可以用小略号取代串末尾的字符使其适合于指定的边界矩形。如果要显示路径信息,指定DT_END_ELLIPSIS标志并省略号取代串中间的字符。
void CSampleView:: OnDraw (CDC* pDC)
{
     CTestDoc* pDoc=GetDocument ();
     ASSERT_VALID (pDoc);
                                                                                   
     //Add ellpsis to end of string if it does not fit
     pDC->Drawtext (CString ("This is a long string"),
         CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS);

     //Add ellpsis to middle of string if it does not fit
     pDC->DrawText (AfxgetApp () ->m_pszhelpfilePath,
         CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS);
}

十一、如何实现一个橡皮区矩形(具有踪迹矩形并可移动、缩放的矩形)
     CRectTracker是一个很有用的类,可以通过调用CRectTracker:: TrackRubberBand响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。下例表明使用CRectTracker移动和重置视窗中的蓝色椭圆的大小是很容易的事情。
    首先,在文档类中声明一个CRectTracker数据成员:
class CTestDoc: Public CDocument
{…
public:
CRectTracker m_tracker;

};
     其次,在文档类的构造函数中初始化CRectTracker 对象:
CTestDoc::CTestDoc()
{
m_tracker.m_rect.SetRect (10, 10, 300, 300);
m_tracker.m_nStyle=CRectTracker:: resizeInside |
CRectTracker:: dottedLine;
}
     然后,在视图类的OnDraw函数中画椭圆和踪迹矩形:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

//Select blue brush into device context.
     CBrush brush (RGB (0, 0, 255));
     CBrush* pOldBrush=pDC->SelectObject (&brush);

     //draw ellipse in tracking rectangle.
     CRect rcEllipse;
     pDoc->m_tracker.GetTrueRect (rcEllipse);
     pDC->Ellipse (rcEllipse);

     //Draw tracking rectangle.
     pDoc->m_tracker.Draw (pDC);
     //Select blue brush out of device context.
     pDC->SelectObject(pOldBrush);
}
    最后,视图类中处理WM_LBUTTONDOWN消息,并增加下述代码。该段代码根据鼠标击键情况可以拖放、移动或者重置椭圆的大小。

void CTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
   //Get pointer to document.
     CTestDoc* pDoc=GetDocument();
     ASSERT_VALID (pDoc);

     //If clicked on ellipse, drag or resize it. Otherwise create a
     //rubber-band rectangle nd create a new ellipse.
     BOOL bResult=pDoc->m_tracker.HitTest (point)!=
         CRectTracker::hitNothing;

     //Tracker rectangle changed so update views.
     if (bResult)
     {
        pDoc->m_tracker.Track (this,point,TRUE);
        pDoc->SetModifiedFlag ();
        pDoc->UpdateAllViews (NULL);
     }
     else
        pDoc->m_tracker.TrackRubberBand (this,point,TRUE);

CView::OnLButtonDown(nFlags, point);
}

十二、如何在临时目录创建一个临时文件
如果你要在临时目录下创建临时文件,下面的代码能帮到你的忙。
bool GetuniqueTempName (CString& strTempName)
{
strTempName="";
     //Get the temporary files directory.
     TCHAR szTempPath [MAX_PATH];
     DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath);
     if (dwResult==0)
   return false;

     //Create a unique temporary file.
     TCHAR szTempFile[MAX_PATH];
     UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempFile);
     if (dwResult==0)
   return false;

     strTempName=szTempFile;
return true;
}

十三、如何限制窗口的最小范围
要限制窗体的大小,下面的代码能帮到你的忙。
在CMainFrame中增加WM_GETMAXMININFO消息的处理函数,然后在这个函数中写代码如下:
//限制主窗体的最小高度和宽度
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
lpMMI->ptMinTrackSize.x=600;
lpMMI->ptMinTrackSize.y=400;
CNewFrameWnd::OnGetMinMaxInfo(lpMMI);
}

十四、怎样删除文件到回收站中
要删除文件到回收站,很简单。只要用SHFileOperation函数就行了,下面的代码我将为你演示了这一个函数的用法。当然你可以直接拷贝到你的项目中。
//删除文件到回收站中
//pszPath : 待删除的全路径文件名
//bDelete : TRUE 删除,不移到回收站,FALSE:移到回收站
一、 //返回    : TRUE 删除成功     FALSE 删除失败
BOOL CDelFileToRecycleDlg::Recycle(LPCTSTR pszPath, BOOL bDelete/*=FALSE*/)
{
SHFILEOPSTRUCT shDelFile;
memset(&shDelFile,0,sizeof(SHFILEOPSTRUCT));
shDelFile.fFlags |= FOF_SILENT;      // don’t report progress
shDelFile.fFlags |= FOF_NOERRORUI;     // don’t report errors
shDelFile.fFlags |= FOF_NOCONFIRMATION;    // don’t confirm delete
// Copy pathname to double-NULL-terminated string.
//
TCHAR buf[_MAX_PATH + 1]; // allow one more character
_tcscpy(buf, pszPath);   // copy caller’s pathname
buf[_tcslen(buf)+1]=0;   // need two NULLs at end

// Set SHFILEOPSTRUCT params for delete operation
shDelFile.wFunc = FO_DELETE;       // REQUIRED: delete operation
shDelFile.pFrom = buf;         // REQUIRED: which file(s)
shDelFile.pTo = NULL;          // MUST be NULL
if (bDelete)
{         // if delete requested..
shDelFile.fFlags &= ~FOF_ALLOWUNDO;    // ..don’t use Recycle Bin
}
else
{           // otherwise..
shDelFile.fFlags |= FOF_ALLOWUNDO;    // ..send to Recycle Bin
}
     return SHFileOperation(&shDelFile);    // do it!
}

十五、内存泄漏检查
    也许你已经知道,在C++和C语言中指针问题也就是内存申请与释放是一个令人头疼的事情,假如你申请了内存,但没有释放,并且你的程序需要长时间地运行,那么,系统的资源将逐渐减少,当系统的资源全部被用完时,系统将会崩溃。所以在开发程序的过程中一定要保证资源的完全释放。下面我们来介绍内存漏洞的检查。
示例如下:
// do your memory allocations and deallocations…
CString s = "This is a frame variable";
#ifdef _DEBUG
CMemoryState oldMemState, newMemState, diffMemState;
oldMemState.Checkpoint();
#endif
// the next object is a heap object
CString* p = new CString( "Smith Alan 581_0215" );
delete p;
p=NULL;
#ifdef _DEBUG
newMemState.Checkpoint();
BOOL b=diffMemState.Difference(oldMemState, newMemState);
if (b)
{
AfxMessageBox( "Memory leaked!n" );
}
#endif
     根据试验,由于我们无法释放掉象int CString char 申请的变量。只能释放指针型的变量。而检测内存时,照样会出现内存泄漏现象。所以,这种内存检测方式局限性还是很大。因为我们无法释放非指针型变量。

Read: 837

不是天才,为什么还要努力?

一个世纪,在此之间诞生的天才是屡见不鲜.先撇开文学政治经济军事类的不谈,光是科学界的都多到我们眼球发花,啊也看不完.甚至你是用走马观花的姿势去浏览,也会觉得不只是"爱"就一个字,人呀,"多"也一个字.但是天才的数目多可是件好事.为什么好呢?因为显而易见嘛:他们推动了科学的发展,为我们一般的人额外支出了巨大的脑力.因为一些深层次的问题,不是你一般的人想学,从而解答,然后造福民众,这样看似顺理成章就能轻松完成.它需要很大的精力和时间,但是更重要的是有良好的IQ.那么不是天才的我们,为什么还要努力,努力的意义是不是也很深远呢?为了回答这个问题,下面我先谈谈那些天才到底"天"在哪里?

先看看数学家高斯的天分:

高斯是一对普通夫妇的儿子。他的母亲是一个贫穷石匠的女儿,虽然十分聪明,但却没有接受过教育,近似于文盲。在她成为高斯父亲的第二个妻子之前,她从事女佣工作。他的父亲曾做过园丁,工头,商人的助手和一个小保险公司的评估师。当高斯三岁时便能够纠正他父亲的借债帐目的事情,已经成为一个轶事流传至今。他曾说,他在麦仙翁堆上学会计算。能够在头脑中进行复杂的计算,是上帝赐予他一生的天赋。

高斯用很短的时间计算出了小学老师布置的任务:对自然数从1到100的求和。他所使用的方法是:对50对构造成和101的数列求和(1+100,2+99,3+98……),同时得到结果:5050。这一年,高斯9岁。

哥廷根大学当高斯12岁时,已经开始怀疑元素几何学中的基础证明。当他16岁时,预测在欧氏几何之外必然会产生一门完全不同的几何学。他导出了二项式定理的一般形式,将其成功的运用在无穷级数,并发展了数学分析的理论.19岁的时候他第一次用圆规构出了规则的17边型.

的确,有良好的数学头脑是高斯老妈给他的.天就天在这,然而对数学的兴趣是使高斯发扬天才之能的后天条件~于是,你还是得相信努力是有意义的.不能因为你脑力有限,而放弃有兴趣但是却很艰辛的工作.

我们大多数人,活在世间,努力都不是为了自己的兴趣.由于世界的飞速发展,时空的不停变换,导致了人们在意识形态上发生了很大的演化.于是,以后的生活都朝着被社会定调了的方向前进,远离了当初在大人面前说出理想时的你.没错,有时侯我们要现实点.比如一个很有能力的青年,在物资条件上遇到了困难,而放弃他的理想,是情有可原的.但是,这一个放弃,或许成就了他另一个人生.他可能凭着他的良好天分,在商场牟了大利,于是官场也逐步参与,入戏接着编剧,最后情场也得意.这个人生看来他会很满意,但是人民群众呢?满意吗?这得看他是不是好商,是否是个好官,他老婆呢?那就看他是个好男人吗.但是我想说,这个年代好商难做,好官不用说了,至于好男人嘛哈哈~~我笑了!

于是,我们可以想见,天才的诞生很容易,只要有好的大脑就行了,可是最后服务人民的天才出来的容易吗?这个很难呀,就好比让习惯开宝马接MM的老板换成用拖拉机去拉客一样,难于上青天.

近代的天才也蛮多的.比如我的偶像:爱因斯坦和霍金,都是物理界的大牌民星.他们的成就是巨大的.前者史无前例的提出了经典的狭义和广义相对论.后者在量子引力论,黑洞理论,和宇宙起源论上的贡献是怎能用三言两语打发了的.当然能做出这翻成就,和人生努力是分不开的.

现在网络发达了,很多有为青年也开始努力了.他们在圈内被称为(奋青),于是每天除了上班或学习,吃饭,约会外他们的努力都用在了网络上.你一言,我一语的讨论得很有气愤,还一边感叹着这电子电脑可不是一般的好,是相当的呀.因为有了它们,骂人可以不用见面,一来少了口水相溅的不卫生,二来少了由口角纠缠导致的肉搏,以及由此衍生的通常的两种可能:进医院或派出所.这时候,他们真实为民的奋斗在现实社会中我们难以寻觅,只能常常看着博客中的风云四起,骂断这方群僚的祖宗后又说抡起斧头要砍你.我欲唤回鲁迅亡灵来和他们说理,又恐他也成了奋青的头领.

总之,人嘛呀总要努力呀,先为自己,再为家人,最后为别人是这个时代的口号~~哈哈,但是人不能老是这样,有时把他人放前,会更有意义,当然会不会有好的待遇,那得看运气和看你咯~~~

Read: 1783

影响照片锐度的15个要素

有读者问:“我用普通35mm底片拍摄,能放大到20英寸吗?”能!因为经过几十年的不断研发,35mm胶卷的工艺极其成熟,不过根据业内专家介绍,实际上它的潜力仍然很大,如果方法适当,放大到20英寸以上毫无问题。

获得高锐度照片,锐度其实不是惟一因素。很多读者将锐度和分辨率混为一谈,其实,决定照片锐度的关键是分辨率而非锐度,而衡量分辨率以线对/毫米(line-pairs per millimeter,有时标注为pmm)为标准。人眼并不能分辨物体的细节本身,而是通过分辨细节的边缘来判定其锐度,因此很多人将高锐度的照片误以为高分辨率的照片,其实这是人眼观察和分辨物体的特点带来的认识误区———数码照片属于高锐度、低分辨率影像,而传统胶卷则是高分辨率、低锐度影像,很多读者认为数码照片分辨率高,正是这种误区的具体体现。顺带提及的是,光学中锐度的英文是“acutance”而非大多数媒体所用的“sharpness”。

回头再看35mm胶卷,由于其画幅很小,因此从拍摄到冲洗以至放大,容不得一点技术上的瑕疵,幸亏由于长时间使用,关于这方面的经验已经十分丰富,读者所要做的就是“知之、行之”。涉及照片锐度的主要包括镜头、胶卷和个人技术等三大方面共15个问题。

1.三脚架 很多摄影技术文章都建议摄影者重视使用三脚架,没有一个要素对影像质量有这么大的影响。但如果使用三脚架,一定要使用高质量的三脚架,不要打“用便宜的三脚架替代高档三脚架”的如意算盘。性能价格比很高的三脚架,每条腿都可以独立打开,而且重量合理、使用方便。有了优质的三脚架,还要有与之相配的云台,不仅应该能够快速装卸,而且可以适用于各种拍摄题材。国外的摄影师往往选择有“三脚架中的卡迪拉克”之称的捷信三脚架,而云台则选择瑞士阿卡照相机工厂生产的球形云台,它不仅能快速装卸,而且质量极为可靠,其加工工艺十分精良,绝对物有所值。使用三脚架时,最好只升到必要的高度,除非万不得已,升起中柱都是最后的选择。另外在刮风的天气里,三脚架的高度越低越好,或者使用重物加固三脚架。

不要被灿烂的阳光所迷惑,必须牢记手持摄影的基本规则:快门速度使用镜头焦距的倒数———即使是心脏的每次跳动,血液在身体里的流动都会导致手震。大多数摄影者都不认为心跳会对成像质量产生什么影响,不过根据有关的测算,脉搏会导致大约0.2毫米的位移,因此快门速度至少不能低于1/10秒。假如您使用的是一只高质量的镜头,其分辨能力为100 lpm,如果使用1/250秒快门速度手持摄影,即使0.2毫米的位移,也会导致其分辨能力降至78 1pm,损失大约22%的分辨能力;若是将快门速度进一步改为1/60秒,分辨率仅为30 1pm。因此,不要相信用60mm尼克尔微距镜头、以1/60秒快门速度手持摄影能够拍摄出足以放大到10英寸以上的照片。记住:使用三脚架是保证成像锐度的必要条件。

2.快门速度 三脚架不可能保证被摄主体不动,即使是拍摄山脉这样的风光题材,也不能忽视风吹叶动这样的问题,一旦这种移动与相机颤动以及其他因素叠加到一起,就会危及成像锐度。需要指出的是,如果您使用变焦镜头拍摄———比如一只70-200mm镜头,手动模式或快门先决模式下为70mm端时设定的最佳快门速度,如果快速变焦到200mm端时可能就忘记提高快门速度了,这时手震的影响急遽加大,会大大影响照片的锐度。

3.快门线 不要以为将相机装到三脚架上就一劳永逸了,要知道按快门的动作不论怎么轻盈,也能引发震动,使用快门线或自拍功能能够最大限度地减小机震问题。

4.对焦精度 有一个极为重要、却往往被忽视的问题:有些戴眼镜的摄影者会发现,戴不戴眼睛时的对焦精度相差很大。您用的是哪种对焦屏?有不少摄影者习惯于使用普通磨砂对焦屏,这种对焦屏适合于水平线较多的场合,但是对焦精度比裂像-微棱镜对焦屏差多了,如果你需要经常使用手动对焦,最好还是使用裂像-微棱镜对焦屏,以便摄影者的视觉可以在1-2秒内分辨出是否精确合焦。

5.使用最佳光圈 一只镜头各个光圈的分辨率相差很大,有时差一二级光圈,锐度就犹如天壤之别,不过事情并不总是这样,若是像f8和f11这样的“最佳光圈”,其分辨率和锐度都十分接近。有时,用f16和f22这样的光圈拍摄,景深很大,给人感觉锐度很大,其实由于衍射问题的影响,分辨率反而会下降。

6.衍射 衍射是一种很怪异的光学现象,当光线通过光圈时,靠近光圈叶片边缘的光线会产生偏移———这就是衍射,而接近光轴的光线则笔直地会聚到焦点上。如果光圈很小,那么衍射现象会变得十分严重。通常,便宜的镜头和光学设计做得较差,衍射问题就更为明显了。很多镜头在f22到f32时,分辨率比f16会下降很多。

7.镜头 买你能买得起的最贵的镜头!这已经是老生常谈了,但很多摄影者仍然做不到这一点。不过目前,很多镜头生产厂商借助超级计算机已经推导出了先进的光学公式,获得了极佳的光学设计,而且这些镜头的成像锐度非常高,却便宜得唾手可得,无论是光学结构、耐用性和可靠性都非常出色。相比之下,一只昂贵的专业镜头并不仅仅是大光圈这一点,如果你用慢速胶卷或使用低感光度设置拍摄,或者遇到其他极端的环境,才能体会出专业镜头在成像锐度上的优势。(未完待续)

来源:中国摄影家协会

Read: 619