Wednesday, January 25, 2006

HTML Validator (Firefox Extension)

Recently, I discovered this tool. And it soon becomes the "must-have" tool for me. I develop web pages using ASP.NET. I always call HtmlEncode function before I insert any text from database to web page. But, there is one problem this function call won't solve. And I didn't notice this problem until I used the "HTML Validator" tool to inspect all the web pages I created.

In this case, I grabbed a piece of text from database and inserted it into the web page as tooltip. I called HtmlEncode function before inserting the text to the "title" attribute. Guess what, I forgot one thing: replace the single quote "'"! So, HTML like this can be generated.
<span title="'blogger's">space<font>

Of course it is wrong. You will only see this tooltip: "blogger". But, no web browsers have complained about this. And no users complained about this (well, they just don't know what they should see). I bet it won't be noticed by anybody not for this wonderful extension.

Link to this extension:
https://addons.mozilla.org/extensions/moreinfo.php?id=249&application=firefox

Tuesday, January 17, 2006

FlashBlock (Firefox extension)

I only have 3 Firefox extensions installed. FlashBlock is one of them.

Pros: It replaces flash animation with a button which user can click to start the flash content. Since 99% of flash contents on the web are Ads that just distract your attention from reading and slow down the CPU, this extension is a big saver. It also has a white list option to allow some customization.

Cons: Uninstall is not as easy as install. There are other known problems.

Thursday, January 12, 2006

Dialog Data Validation for MFC

Problem: Data validation in MFC is a bit difficult. We only get
a couple of DDV functions that left a lot to be desired. For example, there is
no easy way to make sure a “Dropdown Combo Box” is not empty.


Solution: After some searching in MSDN documents and
googling, I cannot find a good clean solution. But, I am inspired by the MFC
source code and found the following solution.


In the "DoDataExchange" function of your dialog, you only need to add a few
lines of code (highlighted below) to validate an empty combo box.
Following this logic, you can easily add more sophiscate validation logic, and
make sure the focus will be set to the control that you want user to change.


void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CMyDlg::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTaskMTTPage)
DDX_CBString(pDX, IDC_COMBOFILENAME, m_strFilename);
//}}AFX_DATA_MAP

//customized data verification
if(pDX->m_bSaveAndValidate)
{
//we will only check data during validation
if(m_strFilename.IsEmpty())
{
CString errorMessage = "The file name field cannot be empty.";
AfxMessageBox(errorMessage, MB_ICONEXCLAMATION);
errorMessage.Empty();

pDX->PrepareCtrl(IDC_COMBOFILENAME); //make sure pDX will focus to this control
pDX->Fail();
}
}

}

Extra: In the process of searching for the solution mentioned
above, I found this interesting problem: VC7 and VC98 have slightly different
definition of public members of CDataExchange class (notice the highlighted
code segment below). Why should Microsoft change definition of public member of
their library? Isn't public member supposed to be some sort of binding
contract?


Another interesting discovery is that Visual Studio intell-sense won't show "m_hWndLastControl"
although it is public member of the class. Did I miss something here?


Why do I care about this obscure member of CDataExchange? Well, I
am trying to find a way to make sure the dialog will set focus on the correct
control after an error condition occurs. My first intent was to manipulate the
m_hWndLastControl
or m_idLastControl member, thus lead
to the discovery. Eventually, I found out calling function PrepareCtrl
is a much better solution.


Definition of class CDataExchange in VC98 include:

// CDataExchange - for data exchange and validation
class CDataExchange
{
// Attributes
public:
BOOL m_bSaveAndValidate; // TRUE => save and validate data
CWnd* m_pDlgWnd; // container usually a dialog

// Operations (for implementors of DDX and DDV procs)
HWND PrepareCtrl(int nIDC); // return HWND of control
HWND PrepareEditCtrl(int nIDC); // return HWND of control
void Fail(); // will throw exception

#ifndef _AFX_NO_OCC_SUPPORT
CWnd* PrepareOleCtrl(int nIDC); // for OLE controls in dialog
#endif

// Implementation
CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate);

HWND m_hWndLastControl; // last control used (for validation)
BOOL m_bEditLastControl; // last control was an edit item
};


Definition of class CDataExchange in VC7 include:

// CDataExchange - for data exchange and validation
class CDataExchange
{
// Attributes
public:
BOOL m_bSaveAndValidate; // TRUE => save and validate data
CWnd* m_pDlgWnd; // container usually a dialog

// Operations (for implementors of DDX and DDV procs)
HWND PrepareCtrl(int nIDC);
HWND PrepareEditCtrl(int nIDC);
void Fail(); // will throw exception

CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate);

#ifndef _AFX_NO_OCC_SUPPORT
COleControlSite* PrepareOleCtrl(int nIDC); // for OLE controls in dialog
#endif

// Implementation
UINT m_idLastControl; // last control used (for validation)
BOOL m_bEditLastControl; // last control was an edit item
};