⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vc小知识总结(续).txt

📁 一些学C的忠告以及有小程序可学习。应该是终生受用的。
💻 TXT
📖 第 1 页 / 共 5 页
字号:


我在OCX(对象连接和嵌入客户控制程序)有一个非模态对话框.它有一个菜单以及工具条.现在我想Disable客户区(只是客户区,例如:设置特殊变量时显示一个等待光标,区域里的所有控制都不可以处理)但在客户区的所有控制要看上去没有变化(也就是不可以Disable)

可以这样试一下,建立一个子窗口,覆盖对话框的全部的用户区域,用WS_EX_TRANSPAPENT 透明类型,然后调用函数EnableWindow(FALSE),使用SetClassLong或者别的方法,在子窗口调用"忙"光标,这时光标就正确了,但对话框中的菜单还能正常使用.(说白了就是建立一个透明的子窗口盖住所有的用户区域,然后Disable该透明窗口,在这个窗口中设置光标为"忙") 这个方法我没有试过,但在一些老的Windows的书介绍过这种方法.

(57)关于使用SetClassLong和SetCapture问题


我用SetClassLong设置对话框光标时遇到了一些问题,当我使用SetCapture捕获鼠标时,

光标形状并没有变化时,以下为原代码:

void CMouseMoveSimDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
  myDragging = TRUE;

  myhPrevCursor = (HCURSOR)SetClassLong( m_hWnd, GCL_HCURSOR,
   (long)LoadCursor(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDC_SELECTCURSOR )));

  SetCapture(m_hWnd);
CDialog::OnLButtonDown(nFlags, point);
}
如果移去SetCapture这一行,光标就会正确的设置,但它就不能正确的捕获鼠标消息.那儿出问题了(环境NT4.0 VC6.0)?

1).如果我没有记错的话,SetClassLong只影响调用它以后的建立的窗口.可以使用 SetWindowLong来改变已存在的窗口的属性.(为什么要用SetClassLong来改变光标形状, 为什么不在消息WM_SETCURSOR中替换.)
2).我也不清楚问题出在那儿,但下面的方法可以克服SetCapture带来的问题,它是从我的程序里面提出来的:


void CScribbleView::OnLButtonDown(UINT nFlags, CPoint point)
{
    ........
    SetCapture(); // Capture the mouse until button up

    myhPrevCursor = (HCURSOR)SetClassLong( m_hWnd, GCL_HCURSOR,

(long)LoadCursor(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDC_CURSOR1)));

SetCursor(LoadCursor(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDC_CURSOR1)));
    ........
}

void CScribbleView::OnLButtonUp(UINT nFlags, CPoint point)
{
    if( GetCapture() != this )
        return;
    ........
    ReleaseCapture();
    SetClassLong( m_hWnd, GCL_HCURSOR, (long)myhPrevCursor);
    return;
}


(58)动画控件?


我在对话框中使用一个动画控件,通常我都是用CAnimated的open成员函数,并加上avi的文件名来使用动画控件,怎样在资源文件加入一个avi文件,作为资源使用?

1).简单,将avi文件引入资源,按你的喜欢来决定是属于那一种类型的,通过ID来代替文件的名字,这样你就可以使用了.
2).在资源窗口中单击右键,在弹出的菜单中选择"Import".这时会打开文件选择框,选择所要的文件,这时系统将会询问自定义资源类型,输入avi.一个AVIS的资源组将会创立,你所选的avi文件将会出现在该组中并拥有一个ID.
3).手动在资源文件中加入一个AVI资源说明,比如:
//在这手工编辑资源文件
IDR_ANIMATION AVI res\animate.avi

(59)错误声明的消息?


我给一个视发送一条消息
pView->SendMessage (MY_MESSAGE, wparam, lparam);
消息声明被认为是不正确的
afx_msg void OnMyMessage();
高手一看就知道这是一条命令错误的声明对象,正确的声明应该为:
afx_msg LERSULT OnMyMessage (WPAPRAM wparam, LPARAM lparam);

因为我不使用参数,程序工作也很好,所以我不知道为什么会有这种错误,该过程处理完之后也没有任何错误的信息出现.但现在release版本中有一个奇怪的现象(debug版本中没有)程序会非正常终止,通常这现象发生在SendMessage()返回之后。为什么?

1.相信问题是出在错误的堆栈上,"thiscall"调用后就应该清除堆栈,调用者调用时将两个参数压入堆栈,但参数却没有被清除.如果你真的不需要WPARAM,LPARAM,也不需要返回值的话,你可以使用ON_MESSAGE_VOID 消息声明.在afxpriv.h中定义,是非文档的,意思就是它不会有什么提示或可能中断程序, 另外,需要注意一下线程消息,注意线程消息是可变的,它们将返回void,没有LRESULT,同样的声明.
2.如果你不使用WParam和LParam,为什么不在视中定义一个用户函数来处理自己想做的?

(59)怎样模拟鼠标动作?


这是困扰我多时的一个问题,怎样才能实现模拟鼠标的动作,就是说要使一个程序实现鼠标的单击,双击,拖放等功能.我认为必须要实现相应的消息传递,但每次都不成功.
比如说,我想关闭记事本窗口,可以传送WM_lBUTTONDOWN和WM_LBUTTONUP(X,Y值为记事本的右上角关闭按钮的位置)给记事本窗口,但窗口并没有关闭.当然,我也知道关闭一个窗口可以通过传送WM_QUIT或WM_CLOSE来实现,但鼠标的消息为什么会丢失?
请教各位大师,怎样模式模拟实现鼠标的动作,或者给我一些怎样发送消息来关闭窗口的建议(不是WM_CLOSE或WM_QUIT)

1).试一下window hooks,你可以使用SetWindowsHookEx和JournalPlayback来处理鼠标事件.
2).你可以使用文档中的SendInput(),它能实现模拟键盘或鼠标事件.如果你使用NT,那也可以用老的函数像mouse_event(),keyb_event等,在Win98中,SendInput()一样可以使用.
3).抱歉不能给你一个满意的回答,你可以在网站http://www.microsoft.com/enable/dev/tooldev.htm 中找到一篇关于模拟输入的文章.
4).在NT中可以使用mouse_event()传递事件,文档上说这种方法已经过时了,那么你可以用 SendInput()替换,但找不到关于此函数的使用说明,所以我依然使用mouse_event,没有任何问题.

(60)改变对话框标题字体?


怎样改变对话框标题文件的字体,改变资源中对话框属性中的字体,将改变所有的控件的字体, 却没有改变标题,但我只想改变标题字体,不改基余控件的属性.是不是我错过一些明显的选项. 通过查找一些MFC代码,我发现有一个CDialog模块,里面调用了一引起字体方法,但该对话框不是公用的,我相信它不会给我任何帮助.

1).就我所知,对话框的标题字体和其它的窗口标题一样,它可以通过系统--显示器--属性--外观来设置,如果自己想这样做,我想你应该取得WM_NCPAINT句柄自己来画出非用户区域(包括标题在内),我从未做这样做过,可能是个错误的方向.
2).如果你是在CView继承的,那你可以在构造函数中看见如下代码:


if( !my_CFont .CreatePointFont( 180,"Helvetica",NULL ) )
        return false;
GetEditCtrl().SetFont( &my_CFont ,true )
接下来如果你想改变在对话框中的一个CEdit控件字体时,可以使用以下代码:

if( !my_CFont .CreatePointFont( 180,"Helvetica",NULL ) )
        return false;
( GetDlgItem (ID_ANY_CEDIT) ) ->SetFont( &my_CFont );

(61)怎样知道CWinThread对象的状态?


怎样才能知道一个线程是在运行还是已经终止?

可以利用线程句柄所指的::GetExitCodeThread()函数,如果线程已经结束, 它将返回一个退出代码,如果还在运行,则返回一个STILL_ACTIVE.不过在之此前,先将 CWinThread成员对象m_bAutoDelete设置为FALSE.另外对象在线程结束时会自动检测到.

(62)如何调整控件对话框条的大小?


我想让用户能够在控制条出现时控制它的大小,在所有的例子中,在控件浮动时,改变尺寸还可以,但在工具条停靠在框架上时就无法调整其大小,该怎样实现?

1)也许你错过了一些注意点,我用的是codeguru站点上下载的CCoolDialogBar类, 在工具条停靠时也可以重新改变其大小.
2)我开发了一个应用程序,它的界面跟你所说的差不多,让我试着解释一下我是怎样做的.
1.从CDialogBar类中继承一个类,名为CMyBar;
2.在CMyBar中增加一个成员变量,int m_iWidth;
3.在CMyBar中的OnPaint和OnNcPaint中画出工具条(grab bar);
4.拖动工具条时在鼠标事件时绘出轨迹;
5.释放鼠标时,计算CMyBar新宽度.可以通过取得当前轨迹位置,使m_iWidth等于新的宽度;
6.(重要)GetDockingFrame()->RecalcLayout();
7.在CMybar中增加一个成员方法CalcDynamicLayout;
8.在CalcDynamicLayout中,当工具条停靠时,通过计算m_iWidth返回值.
当然,这只是一个很简单的方法,你可以做得比这更好.
3)可以试一下VC6.0中的CReBar类

(63)如何顶端显示CStatic类文字?


我正写一个小的应用程序,我想显示一串文本(CStatic)并且无论别的应用程序运行时是否覆盖,这些文字总会在最上面显示.

1)用CreateEx来建立一个WS_POPUP窗口,使这个窗口总在最上面(always on top) 然后在该窗口中实现文字显示.
2)建立窗口时用SetWindowPos()函数,用&wndTopMost作为第一个参数,这样就可以完成你想做的了.

(64)消息句柄出了什么事?


我在CParentView中为WM_LBUTTONDOWN定义一个句柄,但我建个新的CChildView, 句柄得不到处理.

1)仔细看一下你ChildView文件中的MESSAGE_MAP,可能在第两个参数匹配 BEGIN_MESSAGE_MAP(Child,Parent)中有着错误的基类.如果你是用向导生成器, 那么你很容易就会发生这种事情.
2)检查一下消息映象宏中的类名和父类名是否正确,比如BEGIN_MESSAGE_MAP (CChildView,CParentView).
如果你用自己的消息句柄手工代替了向导所做的,确信你的改动是正确的, 一个错误的参数或者加了一个"const"将会改变消息映象而不会被正确调用.
3)我猜想你一定是用类向导生成器来建立你的CChildView,而且在基类的选择中一定是选了CView,自己动手在消息映象中把它修改过来.

(65)树形控件为何闪烁?


我从CTreeCtrl中继承了一个类,以缩进的格式显示节点,现在我碰上些问题,当树被重画两次之后(一次为缺省,另一次为对齐文本时)点选节点树就会闪烁.

1)试一下LockWindowUpdate()API函数。
2)试一下加入TVS——HASBUTTONS标志,

ModifyStyleEx(TVS_HASBUTTONS, 0);
....//drawing
ModifyStyleEx(0, TVS_HASBUTTONS);
如果它不再闪烁,那么在将其定义为自画属性,用PreCreateWindow()中加入CS——OWNDC。

(66)怎样才能关闭树形控件中的滚动条?


我想关闭树形控件的滚动条,但它依然显示出来,怎样才能隐藏它?

1)在建立时加入TVS_NOSCROLL,注意此时你就不可以用键盘来实现翻页,这种类型需要comct32.dll4.71版本以上才可以,并且要在commctrl.h中定义如#define TVS_NOSCROLL 0x2000.
2)值得这样试一下 ModifyStyle(WS_VSCROLL,0),将这段代码放在建立之后,显示之前。

(67)如何建立一个带滚动条的窗口?


我想建立一个带滚动的子窗口,但我没有用向导生成器。

如果你让你的窗口有一个滚动条,你必须首先初始化。如下

   SCROLLINFO si;
   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = SIF_PAGE | SIF_RANGE;

   si.nMin = 0;
   si.nMax = 100;
   si.nPage = 10;
   SetScrollInfo( SB_HORZ, &si );

   si.nMin = 0;
   si.nMax = 50;
   si.nPage = 5;
   SetScrollInfo( SB_VERT, &si );
如果程序运行时你的窗口内容已经改变或者窗口被改变大小而重画时,你必须重新设置滚动条。在MFC中包含类CScrollView,它已内建滚动条。

(68)如何实现对话框的拖放?


我有一个对话框程序,想让它实现拖放。但无论用OnDrag或OnDrop等等,所有的的消息都发送给CView类而不是CDialog类,为什么?

你应该使用COleDropTarget类,试一下这些:

class CMyOleDropTarget: public COleDropTarget
{
protected:
    virtual DROPEFFECT OnDragEnter( CWnd* pWnd, COleDataObject*
pDataObject, DWORD dwKeyState, CPoint point )
    {
        TRACE( "DRAG Enter\n" );
        return DROPEFFECT_MOVE;
    };

    virtual DROPEFFECT OnDragOver( CWnd* pWnd, COleDataObject*
pDataObject, DWORD dwKeyState, CPoint point )
    {
        TRACE( "DRAG Over\n" );
        return DROPEFFECT_MOVE;
    };
};

CMyOleDropTarget DropTarget;

BOOL CDlgDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    DropTarget.Register( this );

不要忘记调用AfxOleInit()
BOOL CDlgApp::InitInstance()
{
    AfxEnableControlContainer();
    AfxOleInit();

}

(69)TrackMouseEvent()怎么了


我使用TrackMouseEvent()函数来跟踪鼠标是否已经离开我的窗口,但在MFC中,如果我使用 ::TrackMouseEvent()系统告诉我没有定义,为什么?

1).请使用_TrackMouseEvent
2).在commctrl.h显示为_TrackMouseEvent(),请注意下划线.
3).可能TrackMouseEvent()不支持Win98(在NT中工作得非常好),建议你结合WM_MOUSEMOVE消息和 SetCapture()函数,当鼠标移出窗口时你依然可以控制.


(70)奇怪的组合框控件


我有一个对话框程序,里面只有几个下拉式给合框.但当鼠标箭头移动到组合框的上下按钮时,会变成"6"或"9",一会儿又恢复到原状,这是为什么?

1)也许是你的操作系统有问题,不防重新起动一次也许就行了(概率非常小8%-())你也可以试一下系统清除工具,如果这事情经常发生,可能你真的需要重装一下95或NT,这也是个好的建议,每隔半年左右可以重装一下系统.
2).我猜想可能是comctl32.dll文件被破坏了.
3).这个问题的原因很有可能是系统的资源不够,你可以试着关闭一些程序、减少屏幕的分辨率来增加一些系统资源。

(71)关于使用MS SANS SERIF字体


我看过好多关于创建对话框、组合框等等使用MS SANS SERIF的例子,自己也做过多次。如: m_font.CreatePointFont (80, _T("MS Sans Serif")); 或 m_font.Create (-8, ....., _T("MS Sans Serif")); 那么想问一下:1)该字体是否在所有的版本中都能实现(包括国际版本) 2)在控制面板上有没有更好的字体代替“SYSTEM”字体?如果有人这样做了,那又是怎样设置字体大小等相关设置的?我希望有一个彻底的方法来选择组合框等的字体。

1)有件事情我做过,在我所有的程序界面中都改变了字体.消息框来显示用户选择的字体. 菜单,工具条以及其他控件的字体都随用户意愿改变.但在对话框中最好还是用对话框编辑器, 其基本字体都是MS SANS SERIF,所以我也以这种字体来作为所有的用户界面. 以下为我所做的代码:


// here's the font I use:
SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
m_fntUI.CreateFontIndirect(&ncm.lfMessageFont);

// here's the code to change the font for a wnd and all it's children, and
resize the controls appropriately
void ChangeDialogFont(CWnd* pWnd, CFont* pFont, int nFlag)
{
CRect windowRect;

// grab old and new text metrics
TEXTMETRIC tmOld, tmNew;
CDC * pDC = pWnd->GetDC();
CFont * pSavedFont = pDC->SelectObject(pWnd->GetFont());
pDC->GetTextMetrics(&tmOld);
pDC->SelectObject(pFont);
pDC->GetTextMetrics(&tmNew);
pDC->SelectObject(pSavedFont);
pWnd->ReleaseDC(pDC);

long oldHeight = tmOld.tmHeight+tmOld.tmExternalLeading;
long newHeight = tmNew.tmHeight+tmNew.tmExternalLeading;

if (nFlag != CDF_NONE)
{
  // calculate new dialog window rectangle
  CRect clientRect, newClientRect, newWindowRect;

  pWnd->GetWindowRect(windowRect);
  pWnd->GetClientRect(clientRect);
  long xDiff = windowRect.Width() - clientRect.Width();
  long yDiff = windowRect.Height() - clientRect.Height();

  newClientRect.left = newClientRect.top = 0;
  newClientRect.right = clientRect.right * tmNew.tmAveCharWidth /
tmOld.tmAveCharWidth;
  newClientRect.bottom = clientRect.bottom * newHeight / oldHeight;

  if (nFlag == CDF_TOPLEFT) // resize with origin at top/left of window
  {
   newWindowRect.left = windowRect.left;
   newWindowRect.top = windowRect.top;
   newWindowRect.right = windowRect.left + newClientRect.right + xDiff;
   newWindowRect.bottom = windowRect.top + newClientRect.bottom + yDiff;
  }
  else if (nFlag == CDF_CENTER) // resize with origin at center of window
  {
   newWindowRect.left = windowRect.left -
       (newClientRect.right - clientRect.right)/2;
   newWindowRect.top = windowRect.top -
       (newClientRect.bottom - clientRect.bottom)/2;
   newWindowRect.right = newWindowRect.left + newClientRect.right + xDiff;
   newWindowRect.bottom = newWindowRect.top + newClientRect.bottom + yDiff;
  }
  pWnd->MoveWindow(newWindowRect);
}

pWnd->SetFont(pFont);

// iterate through and move all child windows and change their font.
CWnd* pChildWnd = pWnd->GetWindow(GW_CHILD);

while (pChildWnd)
{
  pChildWnd->SetFont(pFont);
  pChildWnd->GetWindowRect(windowRect);

  CString strClass;
  ::GetClassName(pChildWnd->m_hWnd, strClass.GetBufferSetLength(32), 31);
  strClass.MakeUpper();
  if(strClass==_T("COMBOBOX"))
  {
   CRect rect;
   pChildWnd->SendMessage(CB_GETDROPPEDCONTROLRECT,0,(LPARAM) &rect);
   windowRect.right = rect.right;
   windowRect.bottom = rect.bottom;
  }

  pWnd->ScreenToClient(windowRect);
  windowRect.left = windowRect.left * tmNew.tmAveCharWidth /
tmOld.tmAveCharWidth;
  wind

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -