为什么我的自定义CStatic派生控件没有收到WM_SIZE消息?

时间:2010-03-16 12:40:47

标签: visual-c++ windows-mobile mfc custom-controls

我目前正在开发一个源自CStatic MFC类(智能设备C ++项目)的自定义控件。 我使用VC ++ MFC类向导创建了控件类,选择CStatic类作为其基类。我已经使用Class View为我的控件类添加了OnSize事件处理程序(我从消息列表中选择了WM_SIZE消息),并且Visual Studio创建了新的OnSize方法以及BEGIN_MESSAGE_MAP(...)和END_MESSAGE_MAP之间的ON_WM_SIZE()语句()。 问题是我的控件没有收到WM_SIZE因此永远不会调用OnSize方法 - 我使用MoveWindow来改变我的控件的大小 - 它的大小改变,就像我在对话框窗口中看到的那样,但WM_SIZE消息永远不会被发送。当我通过SendMessage或PostMessage函数发送WM_SIZE时 - 正常调用控件OnSize方法。我错了什么?我已阅读有关CStatic控件的MSDN文档,并且没有任何信息表明WM_SIZE消息永远不会发送到静态控制窗口。

抱歉我的英语不好。

2 个答案:

答案 0 :(得分:0)

对于基于Windows对话框的项目,我测试了您描述的内容。在调用MoveWindow后,我在自定义控件中收到WM_SIZE消息。您是否可以发布一些源代码,特别是对于您在测试中使用自定义静态控件的对话框类?

发布代码后更新

你在调试器中运行了吗?我想知道为什么在打开对话框时不会立即得到异常,因为CThreatSelection :: OnSize作为第一个事件之一被触发,甚至在控件的窗口句柄threatGrid.m_hWnd存在之前。因此,在对话框打开时,在OnSize对话框事件中调用threatGrid.MoveWindow会导致异常。

我不确定您要实现的目标,但看起来您希望在对话框打开后立即根据对话框大小调整自定义静态值:

为此,可能的替代方案可能是:移除CThreatSelection::OnSize并放入CThreatSelection::OnInitDialog代替:

CThreatSelection::OnInitDialog()
{
    CDialog::OnInitDialog();

    // ... perhaps other Init-Stuff...

    CRect rect;
    GetClientRect(&rect);

    threatGrid.MoveWindow(0,0, rect.Width(), rect.Height(), FALSE);

    return TRUE;
}

您可以在此处调用threatGrid.MoveWindow,因为已在threatGrid.m_hWnd中创建了窗口句柄OnInitDialog

答案 1 :(得分:0)

下面是MFC向导生成的基于CDialog的窗口的标题

#pragma once
#include "threatgrid.h"
#define COLUMN_COUNT 4
// CThreatSelection dialog

class CThreatSelection : public CDialog
{
    DECLARE_DYNAMIC(CThreatSelection)

public:
    CThreatSelection(CWnd* pParent = NULL);   // standard constructor
    virtual ~CThreatSelection();

// Dialog Data
    enum { IDD = IDD_THSELECT };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
private:

public:

    // My custom cotrol field
    CThreatGrid threatGrid;
    afx_msg void OnSize(UINT nType, int cx, int cy);
};

这是te body:

// ThreatSelection.cpp : implementation file
//

#include "stdafx.h"
#include "SpeedNotifyNative.h"
#include "ThreatSelection.h"


// CThreatSelection dialog

IMPLEMENT_DYNAMIC(CThreatSelection, CDialog)

CThreatSelection::CThreatSelection(CWnd* pParent /*=NULL*/)
    : CDialog(CThreatSelection::IDD, pParent)
    , threatGrid(theApp.imaging, 3)
{

}

CThreatSelection::~CThreatSelection()
{
}

void CThreatSelection::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_THGRID, threatGrid);
}


BEGIN_MESSAGE_MAP(CThreatSelection, CDialog) 
    ON_WM_SIZE()
END_MESSAGE_MAP()


// CThreatSelection message handlers

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

    // TODO:  Add extra initialization here
    return TRUE;  // return TRUE unless you set the focus to a control
    // EXCEPTION: OCX Property Pages should return FALSE
}


void CThreatSelection::OnSize(UINT nType, int cx, int cy)
{
    threatGrid.MoveWindow(0,0, cx, cy, FALSE);
    //threatGrid.SizeChanged(cx,cy); I use it normally because no WM_SIZE is sent to threatGrid
    CDialog::OnSize(nType, cx, cy);
    // TODO: Add your message handler code here
}

...我的自定义控件标题:


#pragma once
#include "atltypes.h"
#include "GridIcon.h"

// CThreatGrid
class ImagingSystem;
class CThreatGrid : public CStatic
{
    DECLARE_DYNAMIC(CThreatGrid)

public:
    CThreatGrid(ImagingSystem* imaging, int cols);
    virtual ~CThreatGrid();

protected:
    DECLARE_MESSAGE_MAP()

private:
    // Obiekt podsystemu obrazowania
    ImagingSystem* imaging;
    // Ilość kolumn w siatce
    int columns;
    // Spacing elementów
    int spacing;
public:
    // Informuje kontrolkę o zmianie rozmiaru - dotychczas nie udało mi się znaleźć rozwiązania dlaczego WM_SIZE nie ejst wysyłane
    void SizeChanged(int cx, int cy);
private:
    // Aktualny rozmiar - śledzony niezależnie aby uniknąć niepotrzebnych przeładowań obrazków
    CSize currSize;
    // Lista ikon
    std::vector icons;
public:
    afx_msg void OnSize(UINT nType, int cx, int cy);
};

...和我的自定义控件正文:


// ThreatGrid.cpp : implementation file
//

#include "stdafx.h"
#include "SpeedNotifyNative.h"
#include "ThreatGrid.h"


// CThreatGrid

IMPLEMENT_DYNAMIC(CThreatGrid, CStatic)

CThreatGrid::CThreatGrid(ImagingSystem* imaging, int cols)
: imaging(imaging)
, columns(cols)
{

}

CThreatGrid::~CThreatGrid()
{

}


BEGIN_MESSAGE_MAP(CThreatGrid, CStatic)

    ON_WM_SIZE()
END_MESSAGE_MAP()


// Informuje kontrolkę o zmianie rozmiaru - dotychczas nie udało mi się znaleźć rozwiązania dlaczego WM_SIZE nie ejst wysyłane
void CThreatGrid::SizeChanged(int cx, int cy)
{
   CSize nSize(cx,cy);
   if(nSize != currSize)
   {
       currSize = nSize;
       int wspc = (int)(0.015 * cx);
       int hspc = (int)(0.015 * cy);
       spacing = (wspc  0 )
        {
            int rows = (icons.size() + columns - 1) / columns;
            int width = (currSize.cx - spacing * (2 + columns - 1)) / columns;
            int height = (currSize.cy - spacing * (2 + rows - 1)) / rows;
            CSize size;
            if ( width Calculate(i / columns, i % columns, abspoint, size, spacing);
            }
        }
   }
}

void CThreatGrid::OnSize(UINT nType, int cx, int cy)
{
    CStatic::OnSize(nType, cx, cy);

    // NEVER CALLED BY SYSTEM 
}