VB6 + VC++ : how to avoid flicker?

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance

From: Marco Segurini (marco_segurini_at_jumpy.it)
Date: 05/03/04


Date: Mon, 03 May 2004 17:22:43 +0200

Hi,

I am trying to avoid flicker in this situation:

1) I create a simple VB6 Window application (a void form) and I define
this code for the form (that has the autoredraw property set to false):

'NOTE: this declaration is in another file
Declare Sub InstallMsgHandler Lib _
"E:\TestMsgHandler\Debug\TestMsgHandler.dll" (ByVal lpPC As Long)

Private Sub Form_Load()
     InstallMsgHandler (Me.hWnd)
End Sub

Private Sub Form_Paint()
     Dim lRet As Long
     Dim rectClient As RECT
     lRet = GetClientRect(Me.hWnd, rectClient)

     Dim hTempDC As Long
     hTempDC = GetDC(Me.hWnd)
     Dim hbr, hbrOld As Long
     hbr = CreateSolidBrush(RGB(255, 0, 0)) 'red
     lRet = FillRect(hTempDC, rectClient, hbr)
     lRet = DeleteObject(hbr)
     lRet = ReleaseDC(Me.hWnd, hTempDC)
End Sub

2) I create a MFC dll and I add a CWnd derived class that subclass the
VB form window:

//memdc.h - //header/implementation for double buffer drawing : see
CODEGURU or CODEPROJECT

#ifndef _MEMDC_H_
#define _MEMDC_H_

//////////////////////////////////////////////////
// CMemDC - memory DC
//
// Author: Keith Rule
// Email: keithr@europa.com
// Copyright 1996-1997, Keith Rule
//
// You may freely use or modify this code provided this
// Copyright is included in all derived versions.
//
// This class implements a memory Device Context

class CMemDC : public CDC {
private:
        CBitmap* m_bitmap;
        CBitmap* m_oldBitmap;
        CDC* m_pDC;
        CRect m_rcBounds;
public:
        CMemDC(CDC* pDC, const CRect& rcBounds) : CDC()
        {
                CreateCompatibleDC(pDC);
                m_bitmap = new CBitmap;
                m_bitmap->CreateCompatibleBitmap(pDC, rcBounds.Width(),
rcBounds.Height());
                m_oldBitmap = SelectObject(m_bitmap);
                m_pDC = pDC;
                m_rcBounds = rcBounds;
        }
        ~CMemDC()
        {
                m_pDC->BitBlt(m_rcBounds.left, m_rcBounds.top, m_rcBounds.Width(),
m_rcBounds.Height(),
                                        this, m_rcBounds.left, m_rcBounds.top, SRCCOPY);
                SelectObject(m_oldBitmap);
                if (m_bitmap != NULL) delete m_bitmap;
        }
        CMemDC* operator->() {
                return this;
        }
};

#endif

// CMyCWnd.h

class CMyCWnd : public CWnd
{
        DECLARE_DYNAMIC(CMyCWnd)

public:
        CMyCWnd();
        virtual ~CMyCWnd();

    bool init(HWND hwnd);

protected:
        DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnPaint();
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};

// MyCWnd.cpp : implementation file
//

#include "stdafx.h"
#include "TestMsgHandler.h"
#include "MyCWnd.h"

#include "memdc.h"

extern "C" void WINAPI InstallMsgHandler(HWND hwnd)
{
    static bool bAlreadyInit = false;
    if (!bAlreadyInit)
    {
       static CMyCWnd wnd;
       bAlreadyInit = wnd.init(hwnd);
    }
}

// CMyCWnd

IMPLEMENT_DYNAMIC(CMyCWnd, CWnd)
CMyCWnd::CMyCWnd()
{
}

CMyCWnd::~CMyCWnd()
{
}

bool CMyCWnd::init(HWND hwnd)
{
    return SubclassWindow(hwnd) != 0;
}

BEGIN_MESSAGE_MAP(CMyCWnd, CWnd)
    ON_WM_PAINT()
    ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

void CMyCWnd::OnPaint()
{
    CRect rectClient;
    GetClientRect(&rectClient);

    CPaintDC dc(this); // device context for painting
    CMemDC memdc(&dc, rectClient);

    Default(); // this call the visual basic application redraw.

    rectClient.DeflateRect(rectClient.Width()/4, rectClient.Height()/4);
    CBrush Brush(RGB(0x80,0x80,0x80));
    memdc.FillRect(&rectClient, &Brush);
}

BOOL CMyCWnd::OnEraseBkgnd(CDC* /*pDC*/)
{
    return FALSE;
}

Running this example I have that VC++ draws on the memory buffer while
VB6 draws on the screen. How may I force VB6 to draw on the replaced
in-memory bitmap ?

Thanks for help.
Marco.

-- 
For direct reply change underscore to dot


Relevant Pages

  • VB6 + VC++ : how to avoid flicker?
    ... I create a simple VB6 Window application (a void form) and I define ... Private Sub Form_Load ... VB6 draws on the screen. ...
    (microsoft.public.vb.general.discussion)
  • Re: ComClass + Events
    ... verwende statt Events lieber Callback. ... erstelle eine Klasse in der du die Referenz vom VB6 Objekt merkst, ... ' A creatable COM class must have a Public Sub New() ...
    (microsoft.public.de.german.entwickler.dotnet.vb)
  • Re: ComClass + Events
    ... verwende statt Events lieber Callback. ... erstelle eine Klasse in der du die Referenz vom VB6 Objekt merkst, ... ' A creatable COM class must have a Public Sub New() ...
    (microsoft.public.de.german.entwickler.dotnet.vb)
  • Re: Handle leak in Windows 2003 Authorization Manager?
    ... Since the sample is in VB6, ... releases it's objects when the sub terminates. ... > keep the Authz context around as long as the app keeps the AzMan context ... > Best regards, ...
    (microsoft.public.platformsdk.security)
  • Re: Retrieving dbcc_name string from a DEV_BROADCAST_DEVICEINTERFACE structure
    ... you can install an event listener for USB ... public static void Main{ ... > NotificationFilter As IntPtr, ByVal Flags As Int32) As IntPtr ... > Public Sub New ...
    (microsoft.public.dotnet.languages.csharp)