Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » CExtGridCellHyperLink: overriding OnHyperLinkOpen Collapse All
Subject Author Date
Ashley Gullen Jan 6, 2007 - 9:35 AM

I want to perform a custom action when a hyperlink property is clicked. I don’t want a web browser to open or anything, just opening a messagebox or similar. I’ve tried overriding all four OnHyperLinkOpenXXX functions, but none of them are ever called. What is the proper way to do this?

Ashley Gullen Jan 8, 2007 - 9:34 AM

Thanks a lot for your help, the OnHyperLinkOpen function is called correctly now. However, I’m having difficulty adding member variables. After some testing I added an integer member to the "Ex" class constructed to "5555", but immediately after creation assigned to "7777". I set a breakpoint in OnHyperLinkOpen and the integer has returned to its constructed value of 5555. Is the class being reconstructed by MFC/Prof-UIS, and if so, is this by design?

Technical Support Jan 9, 2007 - 6:17 AM

Each CExtPropertyValue instance keeps two CExtGridCell objects: the active one and the initial one. The later is used for the reset operation. These objects never appear inside tree grids in the property grid control and are stored inside CExtPropertyValue only. Each tree grid window in the property grid control contains cloned copies of active grid cells in property values. That is why you have different cell copies. When the editing is complete in some tree grid window, the property grid control assigns a new cell value to the active cell in the property value and to the all cells of this property value in other tree grid windows. If you have a combined property store, each property value is a reference to several simple property values and the result of editing is assigned to all the referenced property values. So, if you use a custome grid cell class which contains its specific data members, then it is important to override the CExtGridCell::Assign() virtual method like as follows:

void CYourCell::Assign( const CExtGridCell & other )
{
    ASSERT_VALID( this );
    CBaseCell::Assign( other );
CYourCell * pCell =
        DYNAMIC_DOWNCAST(
            CYourCell,
            ( const_cast < CExtGridCell * > ( &other ) )
            );
    if( pCell != NULL )
    {
        // assign all the specific data members
    } // if( pCell != NULL )
    else
    {
        // clear all the specific data members
    } // else if( pCell != NULL )
}

Suhai Gyorgy Jan 9, 2007 - 3:19 AM

I don’t know the real solution, but can point out some aspects of PropertyGrid that could help you find the problem: For every property you see appearing in the grid there are 3 CExtGridCell objects you have to keep in mind:
- one of them is inside the grid, that is the one users can see.
- there are 2 other cells, these are the ones you get when you call PropertyItem’s ValueActiveGet() and ValueDefaultGet().

When the grid first appears it initializes its cell from the default cell of the corresponding propertyitem. When the user changes something in the cell the grid calls Assign, which is used to copy the new value to the propertyitem’s active cell. When user right-clicks cell and chooses Reset from the context menu, the grid copies content of propertyitem’s default cell into the cell appearing in the grid.

I think it is impossible that some Prof-UIS code changes the value of your member variable. I’m guessing you have some code that changes the member variable to 7777, but you are not aware that and how this code is called. And you should keep in mind that OnHyperLinkOpen is called for the cell appearing in the grid, not for the propertyitem’s active cell. You should tell some more about your classes to find out the real problem. Or try reproducing the problem in a sample application or in any of Prof-UIS samples.

Ashley Gullen Jan 7, 2007 - 10:38 AM

Hi,

Here’s the class I am using to override:

// Overridden OnHyperlinkOpen
class CExtGridCellHyperLinkEx : public CExtGridCellHyperLink {
public:
    virtual bool OnHyperLinkOpen(
        __EXT_MFC_SAFE_LPCTSTR strURL,
        e_OpenMode_t eOM = __EOM_OPEN,
        bool bAllowErrorAlert = false
        ) const {
            MessageBox(NULL, "Link click", NULL, NULL);
            return false;
    }
};



I simply replace the standard class with this "Ex" class in the creation, like so:

CExtGridCellHyperLinkEx* pLink = STATIC_DOWNCAST(CExtGridCellHyperLinkEx,
                         pItem->ValueDefaultGetByRTC(RUNTIME_CLASS(CExtGridCellHyperLinkEx)));

The grid cell contains a hyperlink control, but when clicked, it still opens a browser and tries to visit a website. What am I missing?

Suhai Gyorgy Jan 8, 2007 - 2:29 AM

In SimpleGrids sample you can see that overriding a CExtGridCell-derived class is a little more tricky than overriding a usual class. Here are the code-snippets you have to put in your project (I checked it in PageGrid class of ProfUIS_Controls sample).
In .h:

class CExtGridCellHyperLinkEx : public CExtGridCellHyperLink 
{
	DECLARE_DYNCREATE(CExtGridCellHyperLinkEx);
	IMPLEMENT_ExtGridCell_Clone( CExtGridCellHyperLinkEx, CExtGridCellHyperLink );
	CExtGridCellHyperLinkEx(
		CExtGridDataProvider * pDP = NULL
		);
public:
	virtual bool OnHyperLinkOpen(
		__EXT_MFC_SAFE_LPCTSTR strURL,
		e_OpenMode_t eOM = __EOM_OPEN,
		bool bAllowErrorAlert = false
		) const 
	{
		TRACE0("My HyperLinkOpen called");
		return true;
	}
};
In .cpp:
...
#include ".\pagegrid.h"
 
// moved to top (i.e. before DEBUG_NEW) to avoid
// conflict with MFC’s operator new
IMPLEMENT_DYNCREATE(CExtGridCellHyperLinkEx, CExtGridCellHyperLink);
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
...
And then I used STATIC_DOWNCAST when initializing cells.

With this code you can see the message "My HyperLinkOpen called" in the Output window of the VS when the cell is clicked. In the overriden OnHyperLinkOpen make sure you return true;, because this method is called in CExtGridCellHyperLink::OnClick like this: VERIFY( OnHyperLinkOpen( LPCTSTR(strURL) ) ); So debug version of your project would throw an assert if you returned false.

Although I tried using the cell inside a CExtGridWnd, not a PropertyGrid, the usage must be the same.

Suhai Gyorgy Jan 8, 2007 - 3:58 AM

Sorry, I forgot to paste constructor for the class (this goes in .cpp):

CExtGridCellHyperLinkEx::CExtGridCellHyperLinkEx(
	CExtGridDataProvider * pDP // = NULL
	)
	: CExtGridCellHyperLink( pDP )
{
}

Technical Support Jan 7, 2007 - 10:06 AM

You can override only the CExtGridCellHyperLink::OnHyperLinkOpen() virtual method. All the other methods are invoked from this method. We cannot yet confirm that this method is not called. Please check the signature of yours and the base method. They should be equal.