Hi,
I'm trying to make a custom control to make a message balloon appear when a Cedit is focused. I know there are some classes on the internet but i'd really like to make one by myself. The problem i got is when i call the function Create(), there is no error, but nothing appear and onPaint is never called. If i use the resource editor, it works... Note that my main dialog is a dialog with a bitmap painted on it and have the shape of the bitmap.

myCtrl.cpp
Code:
// BalloonMessage.cpp : implementation file
//

#include "stdafx.h"
#include "TransparentDialog.h"
#include "BalloonMessage.h"

#define BALLONMESSAGE_CLASSNAME    _T("MFCBalloonMessage")

// CBalloonMessage

IMPLEMENT_DYNAMIC(CBalloonMessage, CWnd)

CBalloonMessage::CBalloonMessage()
{
	RegisterWindowClass();
}

CBalloonMessage::~CBalloonMessage()
{
}


BEGIN_MESSAGE_MAP(CBalloonMessage, CWnd)
	ON_WM_PAINT()
END_MESSAGE_MAP()



// CBalloonMessage message handlers



void CBalloonMessage::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: Add your message handler code here
	// Do not call CWnd::OnPaint() for painting messages
	dc.TextOut(0,0,"test");
}

BOOL CBalloonMessage::RegisterWindowClass(void)
{
	WNDCLASS wndcls;
    HINSTANCE hInst = AfxGetInstanceHandle();

	if (!(::GetClassInfo(hInst, BALLONMESSAGE_CLASSNAME, &wndcls)))
    {
        // otherwise we need to register a new class
        wndcls.style            = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
        wndcls.lpfnWndProc      = ::DefWindowProc;
        wndcls.cbClsExtra       = wndcls.cbWndExtra = 0;
        wndcls.hInstance        = hInst;
        wndcls.hIcon            = NULL;
        wndcls.hCursor          = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
        wndcls.hbrBackground    = (HBRUSH) (COLOR_3DFACE + 1);
        wndcls.lpszMenuName     = NULL;
        wndcls.lpszClassName    = BALLONMESSAGE_CLASSNAME;

        if (!AfxRegisterClass(&wndcls))
        {
            AfxThrowResourceException();
            return FALSE;
        }
    }

    return TRUE;
}

BOOL CBalloonMessage::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
	// TODO: Add your specialized code here and/or call the base class

	return CWnd::Create(BALLONMESSAGE_CLASSNAME, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}

void CBalloonMessage::PreSubclassWindow()
{
	// TODO: Add your specialized code here and/or call the base class

	CWnd::PreSubclassWindow();
}

void CBalloonMessage::PostNcDestroy()
{
	// TODO: Add your specialized code here and/or call the base class

	CWnd::PostNcDestroy();
}
myCtrl.h
Code:
#pragma once


// CBalloonMessage

class CBalloonMessage : public CWnd
{
	DECLARE_DYNAMIC(CBalloonMessage)

public:
	CBalloonMessage();
	virtual ~CBalloonMessage();

protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnPaint();
public:
	BOOL RegisterWindowClass(void);
public:
	virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
protected:
	virtual void PreSubclassWindow();
	virtual void PostNcDestroy();
};
the way i change the shape of my dialog :
Code:
CDialog::OnSize(nType, cx, cy);
	// Load the image
	m_hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), "palace.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	if (m_hBitmap == NULL)
	{
		MessageBox("Error loading bitmap");
		return;
	}
	//Get information about the bitmap..
	GetObject(m_hBitmap, sizeof(m_Bitmap), &m_Bitmap);	// Get info about the bitmap 
	// Put the bitmap into a memory device context
	CPaintDC dc(this);
	//get a memory dc object
	CDC dcMem;
	//create a compatible dc
	dcMem.CreateCompatibleDC(&dc);	// Select the bitmap into the in-memory DC
	//Select the bitmap into the dc
	CBitmap* pOldBitmap = dcMem.SelectObject(CBitmap::FromHandle(m_hBitmap));
	//Create a couple of region objects.
	CRgn crRgn, crRgnTmp;
	//create an empty region
	crRgn.CreateRectRgn(0, 0, 0, 0);
	//Create a region from a bitmap with transparency colour of Purple
	COLORREF crTransparent = TRANSPARENTCOLOR;	
	int iX = 0;
	int iY = 0;
	for (iY = 0; iY < m_Bitmap.bmHeight; iY++)
	{
		do
		{
			//skip over transparent pixels at start of lines.
			while (iX <= m_Bitmap.bmWidth && dcMem.GetPixel(iX, iY) == crTransparent)
				iX++;
			//remember this pixel
			int iLeftX = iX;
			//now find first non transparent pixel
			while (iX <= m_Bitmap.bmWidth && dcMem.GetPixel(iX, iY) != crTransparent)
				++iX;
			//create a temp region on this info
			crRgnTmp.CreateRectRgn(iLeftX, iY, iX, iY+1);
			//combine into main region.
			crRgn.CombineRgn(&crRgn, &crRgnTmp, RGN_OR);
			//delete the temp region for next pass (otherwise you'll get an ASSERT)
			crRgnTmp.DeleteObject();
		}while(iX < m_Bitmap.bmWidth);
		iX = 0;
	}
	//Centre it on current desktop
	SetWindowRgn(crRgn, TRUE);
	iX = (GetSystemMetrics(SM_CXSCREEN)) / 2 - (m_Bitmap.bmWidth / 2);
	iY = (GetSystemMetrics(SM_CYSCREEN)) / 2 - (m_Bitmap.bmHeight / 2);
	SetWindowPos(&wndTopMost, iX, iY, m_Bitmap.bmWidth, m_Bitmap.bmHeight, NULL); 

	// Free resources.
	dcMem.SelectObject(pOldBitmap);	// Put the original bitmap back (prevents memory leaks)
	dcMem.DeleteDC();
	crRgn.DeleteObject();