葡京网投哪个正规 > 首页 > VC小知识总结【葡京正网网投】,MFC自绘控件学习总结第二贴

原标题:VC小知识总结【葡京正网网投】,MFC自绘控件学习总结第二贴

浏览次数:115 时间:2020-03-25

class CThread : public CWinThread
{
      DECLARE_DYNCREATE(CThread)
protected:
      CThread(); // protected constructor used by dynamic creation
      afx_msg void OnUserOpen( WPARAM wParm, LPARAM lParm );

1.用鼠标移动基于对话框的无标题栏程序的简单方法

void CVCTestDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
    //一句话解决问题 
    SendMessage(WM_SYSCOMMAND,0xF012,0);
    CDialog::OnLButtonDown(nFlags, point);
}

 

下面这几篇帖子仔细阅读定有意想不到的收获,不只是自绘控件,完全可以让我们对MFC的整体认识都会提升1个等级
MFC中OnDraw与OnPaint的区别:

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

16.如何实现非客户区移动

可用下面二种方法:

  // Handler for WM_LBUTTONDOWN message

 

  void CYourDialog::OnLButtonDown(UINT nFlags, CPoint point)

  {

     CDialog::OnLButtonDown(nFlags, point);

     PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y));

  }

 

  // Handler for WM_NCHITTEST message

 

  LONG CYourDialog::OnNcHitTest( UINT uParam, LONG lParam )

  { 

     int xPos = LOWORD(lParam);

     int yPos = HIWORD(lParam);

     UINT nHitTest = CDialog::OnNcHitTest(CSize(xPos, yPos));

     return (nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;

  }

 

就写这么多吧,个人觉得最有用的资料还是MSDN当然还有强大CSDN,每个控件的自绘都不是固定有规律可循的,不要硬搬乱套,要活学活用。也许你现在才开始学,完全看不懂,没关系大家都是那么过来的啦。

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

4.如何实现点一下对话框外面的区域,自动隐藏对话框?

  [问题提出]
    如果想在点击对话框外面的地方使得对话框关闭,该如何做?

  [解决方法]
    试试下面的代码,原理是在激活对话框时,捕获鼠标的动作,当鼠标点击时判断是否点击在对话框外,是的话就释放对话框.

  [程序实现]
    建立名为My的对话框程序.实现如下步骤:
    在MyDlg.h中加入:

    class CShowWindow1Dlg : public CDialog
    {
     // Construction
     public:
         int m_cx;
         int m_cy;
         ......
    };

    在MyDlg.cpp中:

    //定义消息映象,处理鼠标单击及激活
    BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
        //{{AFX_MSG_MAP(CMyDlg)
        ON_WM_LBUTTONDOWN()
        ON_WM_ACTIVATE()
        //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
    {
        CRect rect;
        GetClientRect(&rect);
        rect.InflateRect(m_cx, m_cy);
  
        //Release dialog if the user click outside it.
        if(!rect.PtInRect(point))
        {
           EndDialog(IDCANCEL);
        }

        CDialog::OnLButtonDown(nFlags, point);
    }

    void CMyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
    {
        CDialog::OnActivate(nState, pWndOther, bMinimized);

        if( nState == WA_ACTIVE || nState == WA_CLICKACTIVE)
            SetCapture();
        else
            ReleaseCapture();
    }

    BOOL CMyDlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
        .....
        
        OSVERSIONINFO info;
        memset((char*)&info, 0, sizeof(OSVERSIONINFO));
        info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        if(GetVersionEx(&info))
        {  //we don't run on Win32s, so check only two values
           if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
           {  //On windows 95
              m_cx = GetSystemMetrics(SM_CXFIXEDFRAME);
              m_cy = GetSystemMetrics(SM_CYFIXEDFRAME);
           }
           else
           {  //On NT
              m_cx = GetSystemMetrics(SM_CXDLGFRAME);
              m_cy = GetSystemMetrics(SM_CYDLGFRAME);
           }
        }
    }

     说明:
     1)WM_ACTIVATE消息在ClassWizard中没有,按如下步骤添加,右击CMyDlg类,选Add Windows Message Handle,接着在Filter for messages available to中选Window,在New Windows messages/events列表中就会出现WM_ACTIVATE,选中,点击Add Handler
     2)SM_CXDLGFRAME,SM_CYDLGFRAME   NT中取得有WS_DLGFRAMEstyle风格的窗口的高和宽 95中已经废弃而采用SM_CX_FIXEDFRAME和SM_CYFIXEDFRAME

 

},这才是程序里面的自绘Edit使用的方法.

void CMyDlg::OnKillfocusAddress()
{
     PostMessage(WM_VALIDATE_PARAMS, ED_ADDRESS, 0L);
}

15.如何在对话框中加入状态条

     定义 CStatusBar 变量:

  CStatusBar m_StatusBar;

     定义状态条指定状态:

  static UINT BASED_CODE indicators[] =

  {

     ID_INDICATOR_CAPS,

     ID_INDICATOR_NUM

  };

     在 OnInitDialog 中加入下面代码:

 

  m_StatusBar.CreateEx(this,SBT_TOOLTIPS,WS_CHILD|WS_VISIBLE|CBRS_BOTTOM,AFX_IDW_STATUS_BAR);

 

  // Set the indicators namely caps and nums lock status

  m_StatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT));

 

  CRect rect;

  GetClientRect(&rect);

             

  m_StatusBar.SetPaneInfo(0,ID_INDICATOR_CAPS,SBPS_NORMAL,rect.Width()/2);

  m_StatusBar.SetPaneInfo(1,ID_INDICATOR_NUM,SBPS_STRETCH ,rect.Width()/2);

 

  RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,ID_INDICATOR_NUM);

  m_StatusBar.GetStatusBarCtrl().SetBkColor(RGB(180,180,180));

 

if(!m_bHover)
DrawBoder();   // 画自己的边界

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

8.动态修改对话框的大小

  [问题提出]
    关于如何动态改变对话框的大小,我做了个Demo,大家看看.

  [程序实现]
     //本函数使用方法: 
     //第一个参数:如果是TRUE表示显示扩展的对话框,如果是FALSE,表示缩小对话框。 
     //第二个参数:表示本对话框的HWND, 
     //第三个参数:表示缩小后大小的控件的ID
    void COptionDlg::ExpandBox(BOOL fExpand, HWND hwnd, int nIDDefaultBox)
    {
         CWnd *pWndBox=GetDlgItem(nIDDefaultBox);
         RECT rcDefaultBox,rcChild,rcIntersection,rcWnd;
         pWndBox->GetWindowRect(&rcDefaultBox);
         HWND hwndChild = ::GetTopWindow(hwnd);
         for (; hwndChild != NULL; hwndChild = ::GetNextWindow(hwndChild,GW_HWNDNEXT)) 
         {
                  ::GetWindowRect(hwndChild, &rcChild);
                  if (!IntersectRect(&rcIntersection, &rcChild, &rcDefaultBox))
                           ::EnableWindow(hwndChild, fExpand);
         }
         ::GetWindowRect(hwnd, &rcWnd);
         if (GetWindowLong(hwnd, GWL_USERDATA) == 0)
         {
                  SetWindowLong(hwnd, GWL_USERDATA,
                           MAKELONG(rcWnd.right - rcWnd.left, 
                           rcWnd.bottom - rcWnd.top));
                  ::ShowWindow(pWndBox->m_hWnd, SW_HIDE);
         }
         ::SetWindowPos(hwnd, NULL, 0, 0,
                  rcDefaultBox.right - rcWnd.left,
                  rcDefaultBox.bottom - rcWnd.top,
                  SWP_NOZORDER | SWP_NOMOVE);
         if(fExpand)
         {
                  DWORD dwDims = GetWindowLong(hwnd, GWL_USERDATA);
                  ::SetWindowPos(hwnd, NULL, 0, 0,
                           LOWORD(dwDims), HIWORD(dwDims), SWP_NOZORDER | SWP_NOMOVE);
                  ::SendMessage(hwnd, DM_REPOSITION, 0, 0);
         }
    }

 

透明窗体: (Menu、窗体、Combobox 都可以参考这种方式实现任意透明度,我也是参考这种方法)

if (MyFont.CreateFontIndirect(&LocalLogFont))
    {
    cMyOldFont = cdc->SelectObject(&MyFont);
    }

3.如何改变框对话或窗体视窗的背景颜色

调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。
BOOL CSampleApp : : InitInstance ( )
{

//use blue dialog with yellow text .
SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 , 255 , 0 ) ) ;

}
需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。
首先,给对话基类增加一人成员变量CBursh :
class CMyFormView : public CFormView
{

private :
CBrush m_ brush ; // background brush

} ;
其次, 在类的构造函数中将刷子初始化为所需要的背景颜色。
CMyFormView : : CMyFormView ( )
{
// Initialize background brush .
m_brush .CreateSolidBrush (RGB ( 0, 0, 255 ) )
}
最后,使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测nCtlColor参量。
HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor )
{
// Determine if drawing a dialog box . If we are , return +handle to
//our own background brush . Otherwise let windows handle it .
if (nCtlColor = = CTLCOLOR _ DLG )
return (HBRUSH) m_brush .GetSafeHandle ( ) ;
return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor );
}

 

WindowProc和DefWindowProc的区别:

// m_pcfYTitle is a CFont* to the selected font.
// m_bTotateYTitle is a bool (==TRUE if rotated)

9.隐藏对话框窗口(窗口没有焦点时)

在程序启动时InitDialog中使用SetWindowPos将窗体设置到屏幕以外
然后再隐藏
1.在OnInitDialog()函数里设置定时器:(WINDOWS   API里面响应消息WM_INITDIALOG)   
  SetTimer(1,   1,   NULL);   
  2.添加处理WM_TIMER的消息处理函数OnTimer,添加代码:    
  if(nIDEvent   ==   1)    
  {   
      DeleteTimer(1);   
      ShowWindow(SW_HIDE);    
  } 

 

3).对于控件的Hover和Leave效果,简单的说 Hover就是鼠标现在浮于控件上面,Leave就是鼠标离开了控件,那么这个效果要怎么实现呢?我直接给源码吧
以Edit控件为列
头文件中加入

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

6.对话框上建立View的方法

OnInitDialog()
{
  CDialog:;OnInitDialog();

CRect rectWindows;
GetWinodwRect(&rectWindows);
CRuntimeClass *pViewClass=RUNTIME_CLASS(CXXXView);
CCreateContext *pContext=new CCreateContext;
pContext->m_pCurrentDoc=NULL;
pContext->m_pCurrentFrame=NULL;
pContext->m_pLastView=NULL;
pContext->m_pNewDocTemplate=NULL;
pContext->m_pNewViewClass=pViewClass;

CWnd *pWnd=DYNAMIC_DOWNCAST(CWnd,pviewClass->CreateObject());
pWnd->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0),this,pContext);
delete pContext;
CXXXView *pView=DYUNAMIC_DOWNCAST(CXXXView,pWnd);
...............
}

 

4).我把以前我看过的帖子整理了下供大家学习参考(由于时间久了,很多帖子都忘记了):

    HTREEITEM hItem = NULL;

18.如何限定对话框大小范围

在 WM_SIZING中加入下面代码:

   void CYourDialog::OnSizing(UINT fwSide, LPRECT pRect)

  {

     if(pRect->right - pRect->left <=200)

       pRect->right = pRect->left + 200;

      

     if(pRect->bottom - pRect->top <=200)

       pRect->bottom = pRect->top + 200;

 

     CDialog::OnSizing(fwSide, pRect);

  }

 

 

然后再CPP中定义:
void CEditEx::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bHover)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bHover= _TrackMouseEvent(&tme);// m_bHover: BOOL型成员变量

(53)如何捕获键盘按键?

14.如何改变对话框的形状

可用下面一些涵数:

 CreatePolygonRgn
     CreateRectRgn
     CreateRoundRectRgn 等.

  CRgn m_rgn;  // Put this in your dialog's header file. i.e. a member variable

 

  // This Gets the size of the Dialog: This piece of code is to be placed in the

  // OnInitDialog Function of your dialog.

 

  CRect rcDialog

  GetClientRect(rcDialog);

 

  // The following code Creates the area and assigns it to your Dialog

  m_rgn.CreateEllipticRgn(0, 0, rcDialog.Width(), rcDialogHeight());

  SetWindowRgn(GetSafeHwnd(), (HRGN) m_rgn, TRUE);

 

自绘按钮2篇帖子:

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

12.如何得到屏幕的真实尺寸(以对话框为例)

[问题提出]
我的屏幕是1024*800,如何得到屏幕的真实大小,我用GetSystemMetrics(SM_CYFULLSCREEN)得到的高度总是小于800
[问题解答]
GetSystemMetrics(SM_CYFULLSCREEN)得到的只是屏幕用户区的大小。要得到屏幕的真实大小需要使用
GetDeviceCaps函数,该API函数原型是这样的:

int GetDeviceCaps(
  HDC hdc,     // handle to DC
  int nIndex   // index of capability
);
///得到屏幕尺寸的代码如下
void CMyDlg::OnPaint() 
{
   CPaintDC dc(this); 
   int cx = ::GetDeviceCaps(dc.m_hDC,HORZRES);///得到宽度
   int cy = ::GetDeviceCaps(dc.m_hDC,VERTRES);///得到高度
   CDialog::OnPaint();

}

 

CEdit::OnMouseMove(nFlags, point);
}
LRESULT CEditEx::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
m_bHover = false;
//
做相应的操作
//
return 0;
}
LRESULT CEditEx::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
//
做相应的操作
//
return 0;
}
绝大多数控件可以用这种方法,不过某些控件,可能需要你在OnMouseMove里面完全模拟出 Hover和Leave的情况,比如程序里面的TabCtrl...

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

5.如何使FormView中显示dialog时,不是凹的

  [问题提出]
  为什么FormView中显示dialog时,是凹的,能不能不这样
  [解决方法]
  在Dialog的属性中:
    增加属性WS_BORDER   或者 WS_EX_WINDOWEDGE
  用程序实现:
  pView->ModifyStyle(,WS_BORDER) 或者pView->ModifyStyleEx(,WS_EX_WINDOWEDGE )

 

不规则按钮实现:

方法一:如果你的竖直对齐是指旋转文本的话,下面的代码会对你有帮助:该代码检查一个Check box控制,查看文本是否需要旋转.

11.怎么让无模式对话框显示在主窗口后面

要解决这个问题的关键在于CDialog的Create并不能建立一个无属主的窗口.必须用另外方式建窗口.   
    
  比如你的对话框类叫CDlgNoOwner,在CMainFrame中加一个CDlgNoOwner类的成员变量,   
  弹出这个对话框的消息处理函数为   
    
  void   CMainFrame::OnNoowner()     
  {  

CDlgNoOwner   *m_dlgTest=new   CDlgNoOwner(this);  
      HWND   hwndDlg=::CreateDialog( AfxGetInstanceHandle(),MAKEINTRESOURCE(                              CDlgNoOwner::IDD),NULL/*owner*/,NULL/*dlgproc*/);
      //注意此处DLGPROC为NULL,并不要紧,因为接下要subclass啦   
      m_dlgTest->SubclassWindow   (hwndDlg);//挂接到成员变量!   
      m_dlgTest->ShowWindow   (SW_SHOW);   
      //这时可以看到一个"自由"的对话框弹出,和你的主窗口是平起平坐的.   
  }   
    
  当然不要忘了在对话框关闭时DestroyWindow()..那都是在对话框类中的标准处理了.

 

 afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);
CPP中加入:
BEGIN_MESSAGE_MAP(CEditEx, CEdit)
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave) 
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
注:ON_WM_MOUSEMOVE() 可以用类向导添加,不过OnMouseLeave,和OnMouseHover是需要手动添加的

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

2.对话框消息映射

有对话框A,B
从A中发消息给B然后B处理。
准备工作,先定义消息,如下
#define WM_B_NOTIFY WM_USER + 300 

首先,必须将B的对话框句柄传送给A,暂时叫m_hWndB;

在A的发送消息的地方这样写:
::SendMessage( m_hWndB,WM_B_NOTIFY,TRUE,NULL );

这样A中的处理就完了,下面说B 中的
首先定义消息处理函数,如下
void B::ModiNotify( WPARAM wParam, LPARAM lParam )
{
    MessageBox("小样,我就不信,搞不定你!");
}

然后加消息隐射,如下:
BEGIN_MESSAGE_MAP(CB, CDialog)
    //{{AFX_MSG_MAP(CRPServerDlg)

    ON_MESSAGE( WM_B_NOTIFY,ModiNotify )

    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

 

CWnd中PreCreateWindow、PreSubclassWindow、SubclassWindow的区别:

1). 使用带WS_EX_CLIENTEDGE标志的::CreateWindowEx来替换::CreateWindow 或者用CWnd::CreateEx替换CWnd::Create.
2).在建立控件之后,调用ModifyStyleEx(0, WS_EX_CLIENTEDGE).

17.如何使对话框初始为最小化状态

在 OnInitDialog 中加入下面代码:

SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, NULL);

 

2).关于Edit的补充说明:我最初的自绘方法是利用 WM_NCPAINT 里面处理的非客户区只是自己画了边界,以实现Hover和Leave不同的边界。不过我后来发现由于非客户区太小了边界也就2像素,如果鼠标移动很快有时 系统不能检测到鼠标当前的状态,所以程序里面的Edit是在OnPaint里面做的绘制,不过有个核心API -Default() 下面看代码
void CEditEx::OnPaint() 
{

CMenu *menu, *popup;
menu = new CMenu();

13.如何在对话框中加入工具条

  在 OnInitDialog 中加入下面代码:

  BOOL CYourDlg::OnInitDialog()

  {

       CDialog::OnInitDialog();  

 

       // Create the toolbar. To understand the meaning of the styles used, you

       // can take a look at the MSDN for the Create function of the CToolBar class.

       ToolBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS |CBRS_FLYBY | CBRS_BORDER_BOTTOM);

 

      // I have assumed that you have named your toolbar's resource as IDR_TOOLBAR1.

      // If you have given it a different name, change the line below to accomodate

      // that by changing the parameter for the LoadToolBar function.

      ToolBar.LoadToolBar(IDR_TOOLBAR1);

 

      CRect rcClientStart;

      CRect rcClientNow;

      GetClientRect(rcClientStart);

 

      // To reposition and resize the control bar

      RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST,0, reposQuery, rcClientNow);

     CPoint ptOffset(rcClientNow.left - rcClientStart.left,rcClientNow.top-rcClientStart.top);

 

     CRect rcChild;

     CWnd* pwndChild = GetWindow(GW_CHILD);

 

     while (pwndChild)

     {

       pwndChild->GetWindowRect(rcChild);

       ScreenToClient(rcChild);

       rcChild.OffsetRect(ptOffset);

       pwndChild->MoveWindow(rcChild, FALSE);

       pwndChild = pwndChild->GetNextWindow();

     }

 

     CRect rcWindow;

     GetWindowRect(rcWindow);

     rcWindow.right += rcClientStart.Width() - rcClientNow.Width();

     rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();

     MoveWindow(rcWindow, FALSE);

 

     // And position the control bars

     RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);

 

     return TRUE;  // return TRUE  unless you set the focus to a control

  }

 

Default();         // 关键

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

7.模态对话框初始显示位置的控制

正确的方法是在OnInitDialog中添加MoveWindow,如: 
     MoveWindow(0, 1, 300, 200); 
    需要注意的是前两个参数不能都为0。如果你确实希望把窗口放在(0, 0)处,可以在对话框设计窗口的属性中选中Absolute Align,然后再加入 
     MoveWindow(0, 0, 300, 200); 
    为什么会是这样?你看了MFC的源程序就会明白。原来MFC在调用你的OnInitDialog之后,会调用CDialog::CheckAutoCenter()(在dlgcore.cpp中)检查是否需要将窗口居中,你看了这个函数后就明白为什么需要上面那么做了。

 

1).补充个高级可重载函数PreSubclassWindow(),我的理解是允许用户在子类化之前再做一额外些处理 ,这个重载函数也是非常重要的,要引起相当的注意。可以在这里改变控件的大小,位置,窗口样式,字体 ,等等.....你能想到的能改的,都可以在这里改.

     myhPrevCursor = (HCURSOR)SetClassLong( m_hWnd, GCL_HCURSOR,

10.如何实现点击对话框外的地方使对话框到主窗口的后面

将桌面做为父窗口
pMDlg = new CMDlg;
pMDlg->Create(IDD_M_DIALOG,CWnd::GetDesktopWindow()/* 设置父窗口 */);
pMDlg->ShowWindow(SW_SHOW); 
然后在任务栏里隐藏对话框程序
如何让对话框应用程序在在任务栏上不出现,并且不隐藏窗口。
[解决方法]
   把对话框的扩展属性修改成为WS_EX_TOOLWINDOW。
[程序实现]
   把对话框的属性设置成为toolwindow,然后在需要的地方执行本代码。
   DWORD Style = ::GetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE);
   Style = WS_EX_TOOLWINDOW ;
   AfxGetMainWnd()->ShowWindow(FALSE);
   ::SetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE,Style); 
   AfxGetMainWnd()->ShowWindow(TRUE);

 

首先感谢大家对第一帖的支持,应一些网友烈要求下面我在关于上一贴的一些补充和说明(老鸟可以无视)
这一贴是实战+理论不知道第一帖的先看第一帖:

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

WM_DRAWITEM与DrawItem()的讨论,对控件自绘很有帮助:

2.当TREE的内容改变时,它默认只将变为可见的节点重绘.另外其它已经是可见的节点没有必要重绘,TREE只是滚动DC的位图而已.
上面的意思是不要绘制你不需要看的节点,那会导致速度降低.建议,测试节点矩形是否在客户区,使得只有需要绘制的节点才会被绘制.
void CIndentTree::OnPaint()
{
    CPaintDC dc(this); // device context for painting

同时推荐几个很好的学习网站: 
(英文)
(英文)

(46) CDC中的竖排文本?

深度剖析消息反射机制:

(48)线程消息?

Custom draw 和 Owner draw 的区别(是全英文,不过要是读懂了对你自绘的思想很有帮助,有时间帮大家翻译下):

下面的代码将会帮你的忙:

PreTranslateMessage和TranslateMessage区别:

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

进度条自绘:http://www.codeproject.com/KB/miscctrl/cprogressctrlst.aspx(有项目源码)

在CTabCtrl的子对话框怎样才能捕获ALT+0组合键

}

(49)TreeCtrl控制的显示速度太慢?

透明控件(多个控件)实现:(有项目源码)

       if( rc.top <= dc.m_ps.rcPaint.bottom &&
          rc.bottom > dc.m_ps.rcPaint.top &&=20
          rc.left <= dc.m_ps.rcPaint.right &&
          rc.right > dc.m_ps.rcPaint.left )
       {
          dis.hwndItem = (HWND)hItem;
          dis.rcItem = rc;
          OnDrawItem(0, &dis, &dc);
       }
    }
}
OnDrawItem函数
1.删掉如下代码:

可以在PreTranslateMessage中截取键盘消息。

UINT nEnable;
nEnable = MF_BYCOMMAND|MF_GRAYED;

CSocket* m_pSocket;
m_pSocket = new CSMSSocket(this);
m_pSocket->Create();
m_pSocket->Bind(m_intHostPort, m_strHostIPAddress);
m_pSocket->Connect(lpszAddress, nPort);
但每次Windows Socket都定向到别的端口,怎样才能定向到同一个端口(环境:95/NT VC5.0).

OnPaint函数
1.可见节点,对于GetFirstVisibleItem和GetNextVisibleItem来讲,是:
   a.根节点;b.父节点已展开的节点;因此,"可见"意味着"没有被未展开的父节点隐藏".当节点滚动到客户外时,它对上述两个函数来讲仍是可见的.

(54)怎样实现3D效果?

LOGFONT LocalLogFont;

//display menu
ClientToScreen(&point);
popup->TrackPopupMenu(
    TPM_LEFTALIGN | TPM_RIGHTBUTTON,
    point.x, point.y, this );
delete menu;
}

         case ED_ADDRESS:
         if( !validateAddress() )
             m_edAddress.SetFocus();
         break;

方法二:还有一段代码可参考:

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

void CPage1::OnRotateytitle()
{
LOGFONT lgf;
m_pcfYTitle->GetLogFont(&lgf);
m_bRotateYTitle=
         ((CButton*)GetDlgItem(IDC_ROTATEYTITLE))->GetCheck()>0;

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

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

我有一个客户socket想在socket中建立一个局域联接.我使用下列顺序:

(55)怎样建立客户CSocket?

(58)动画控件?

m_pcfYTitle->CreateFontIndirect(&lgf);
DrawSampleChart();
}
注意如果你从CFontDialog中选择了不同的字体,你应该自己设定LOGFONT的lfEscapement成员.将初始化后的lfEscapement值传到CFontDialog中.

在设计菜单时设定为GRAYED的菜单项,如何在运行时激活它?

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

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类

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

在COMCTL32.DLL中的旧版本中有些小bug,绘画时会带来一些问题, 你可以使用一些定制代码,在www.codeguru.com站点上有下载,如果你使用的是6.0版本,你也可以使用下列代码(摘自我的mainfrm.cpp文件)

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

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

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,没有任何问题.

(47)如何激活变灰的弹出菜单?

(59)错误声明的消息?

我需要在程序中做一个FLAT工具条,于是我加入一个变量m_wndToolBar. 在程序主体窗口的OnCreate()函数中修改工具条状态(0,TBSTYLE_FLAT). 在NT中运行正常,为什么在95中工具条变得透明?

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

我有一个可运行的程序来实现,不一定很全面,但能工作.

在OnDraw成员函数中我想让文本竖直对齐,但CDC类似乎不支持该处理

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

popup->EnableMenuItem( ID_YOUR_ID, nEnable );

       IMAGEINFO* pinfo = new IMAGEINFO;
       ...
       delete pinfo;
没有必要使用动态的IMAGEINFO变量,你可以将其定义为堆栈变量.
2.GetItemState和GetItemText都是使用的GetItem,因此,你只需调用一次, 就可以从节点获得你要的所有信息.

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

// load menu from resource file
menu->LoadMenu( IDR_POPUPMENU );
popup = menu->GetSubMenu(0); // item 0 is DUMMY

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

(52)关于控件的焦点?

真奇怪,OnUserOpen()函数和OnUserOpen(WPARAM, LPARAM)函数竟然不是一个函数,编译器在查到OnUserOpen(WPARAM, LPARAM)时,不会调用OnUserOpen 莫非有人在消息映象做了什么手脚?

当然,也别忘了以下声明:

m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP |
CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
用CreateEx替换ModifyStyle在同一尺寸的工具条中有些不同((CreateEx 建立的略小些),试一下,如果你仍然有这个问题,检查一下COMCTL32.DLL的版本使用标准按钮替换FLAT.

如何正确地在线程之间传送消息?

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

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

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

void CMyView::OnRButtonDown(UINT nFlags, CPoint point)
{
CScrollView::OnRButtonDown(nFlags, point);

LocalLogFont.lfWeight = fWeight;
LocalLogFont.lfEscapement = Orient;
LocalLogFont.lfOrientation = Orient;

有谁能给我一个有效的方法:当一个控件失去焦点时,怎样管理才能使对话框的焦点进入到正确的控件.

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

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

请看下面的示例代码:

void CMyDlg::OnKillfocusName()
{
     PostMessage(WM_VALIDATE_PARAMS, ED_NAME, 0L);
}

    // redraw only visible items with indentation
    for(
       hItem = GetFirstVisibleItem();
       hItem; hItem = GetNextVisibleItem( hItem ) )
    {
       if( !GetItemRect( hItem, rc, FALSE ) )
          continue;

     return true;
}
上面的代码可以在用户使用TAB键或鼠标操纵时,使用焦点跳至下一个控制.当你想DISABLE一个控件或重设焦点时,会有些问题,特别是在Killfocus事件中。

     default:
         break;
     }

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

// escapement is reckoned clockwise in 1/10ths of a degree:
lgf.lfEscapement=-(m_bRotateYTitle*900);
m_pcfYTitle->DeleteObject();

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

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

(50)关于工具条?

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

    DRAWITEMSTRUCT dis;
    CRect rc;

const int WM_VALIDATE_PARAMS WM_APP + 101;

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

if( your test )
{
   nEnable = MF_BYCOMMAND|MF_ENABLED;
}

我从CTreeCtrl继承了一个TREE控制类,重载主要是为了改写每个节点的文本.我在 OnPaint函数中写了一些代码,但这严重地影响了TREE控制的滚动速度.

bool CMyDlg::OnValidateParams(WPARAM rcId, LPARAM)
{
         switch( rcId )
         {
         case ED_NAME:
         if( !validateName() )
             m_edName.SetFocus();
         break;

其实,这是MFC严密的表现,处理时,通过函数指针来调用,而该指针是由发生的事件所决定的.如果句柄不正确定义的话,调用当然是非法的

strcpy(LocalLogFont.lfFaceName, TypeFace);

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

(56)Disable一个非模态对话框的客户区?

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

void CThread::OnUserOpen( WPARAM wParm, LPARAM lParm )
{
     UNUSED( wParm ) ;
     UNUSED( lParm ) ;
     AfxMessageBox("User Open", MB_OK|MB_ICONEXCLAMATION);
}

1).如果你想用Client Socket,你就不能在connect()之前调用bind(),因为局域端口地址由TCP/IP设置,我们不可能知道下一次将使用那一个端口,我想我们不必这做.
2).看一下Create()的帮助,里面告诉我们必须给Create()指定一个端口值, 缺省的情况为0,也就是由Window为我们选择一个端口,通过Create()将会自动捆绑. 3).我不认为你应该完成所有的工作,但想总是用一个相同的端口来连接远程机器是一个不正确的想法.
问题出在端口数/地址结合必须唯一,如果你想在Create()中指一个固定的端口数,你只能与远程机器建一个单个连接.在你所写的代码中是允许局域端口数可变化,可以打开多个连接来取得相同的地址.在侦听(listening)Socket中有许多理由使用一个固定端口,但在连接(connecting Socket中我想没有太多的必要.

(51)关于线程消息?

在对话框中怎样实现Edit和Listboxes控件的3D效果?(环境95/NT VC5.0)

本文由葡京网投哪个正规发布于首页,转载请注明出处:VC小知识总结【葡京正网网投】,MFC自绘控件学习总结第二贴

关键词:

上一篇:没有了

下一篇:VC的若干实用小技巧,VC6常用操作