Microsoft KB Archive/200491

= BUG: Incorrect Coordinates Passed to OLEDragDrop/OLEDragOver =

Article ID: 200491

Article Last Modified on 11/21/2006

-

APPLIES TO


 * Microsoft Foundation Class Library 4.2, when used with:
 * Microsoft Visual C++ 6.0 Service Pack 5

-



This article was previously published under Q200491



SYMPTOMS
When you use an ActiveX control, such as Microsoft TreeView control and Microsoft ListView control, from the COMCTL32.ocx file, (located in Visual C++ version 5.x), or the MSCOMCTL.ocx file (located in Visual C++ version 6.0) in a Microsoft Foundation Classes (MFC) application, then the x- and y-coordinates that are passed to the OLEDragDrop and OLEDragOver event handlers are incorrect. The passing of these incorrect handlers causes the control's HitTest method to return a wrong value.



CAUSE
The control's HitTest method needs and takes a Twips units and a positive y-coordinate value. However, the y-coordinate is a negative value when it is passed in to the MFC container's OLEDragDrop and OLEDragOver event handlers. In addition, the values passed in are measured in pixel units instead of Twips units.



RESOLUTION
Use the following code to perform the conversion from pixel units to Twips units in the OLEDragDrop/OLEDragOver event handlers:

void ConvertXYtoTwips(float FAR* x, float FAR* y)  { // Get a device context. HDC hdc = GetDC(NULL);

// Determine how many Twips are in one pixel. CPoint pOne(1, 1); SetMapMode(hdc, MM_TWIPS); DPtoLP(hdc, &pOne, 1);

// Convert *x and *y to Twips units. float xx = *x * pOne.x;     float yy = *y * pOne.y;//NOTE: both *y and pOne.y are negative values.

// Release the device context. ReleaseDC(NULL, hdc);

// X and y are in Twips pixel units. *x = xx; *y = yy; }



STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article.



MORE INFORMATION
To better illustrate the usage of the ConvertXYtoTwips function defined in the "Resolution" section, a Microsoft TreeView control (m_TreeView variable) is used in an AppWizard generated MFC Dialog-based container application (m_TestDlg). The following code shows how to highlight a node based on the mouse selection in the OLEDragDrop event handler, OnOLEDragDropTreectrl1, of the dialog box:

BEGIN_EVENTSINK_MAP(CTestDlg, CDialog) //AFX_EVENTSINK_MAP END_EVENTSINK_MAP

void CTestDlg::OnOLEDragDropTreectrl1(     LPDISPATCH FAR* Data, long FAR* Effect,      short FAR* Button, short FAR* Shift, float FAR* x, float FAR* y)   { // Convert x and y to Twips pixel units. ConvertXYtoTwips(x, y);

// Determine which node should be highlighted in the // Microsoft TreeView control. CNode node = m_TreeView.HitTest(*x, *y); if (node) {        VARIANT var; var.vt = VT_DISPATCH; var.pdispVal = node.m_lpDispatch; m_TreeView.SetDropHighlight(&var); }  }

Steps to Reproduce Behavior
 Create an AppWizard dialog-based application with ActiveX Controls support. The dialog class is called CTestDlg. Insert a Microsoft TreeView control into the dialog resource. Use ClassWizard to associate the TreeView control with a member variable called m_TreeView. This association also causes Visual C++ to insert the C++ wrapper classes for the TreeView control into the project.  Add some nodes to the TreeView control in response to the WM_INITDIALOG message of the CTestDlg dialog class. The following code sample illustrates this addition: // The node becomes a child node of the node named it is connected to. #define tvwChild  (short) 4

#include "node.h"    // for CNode class BOOL CTestDlg::OnInitDialog {     CDialog::OnInitDialog;

// ...

m_TreeView.SetOLEDropMode(1);

CNodes nodes = m_TreeView.GetNodes; nodes.Clear;

COleVariant NOPARAM( DISP_E_PARAMNOTFOUND, VT_ERROR );

CNode node = nodes.Add(        LPVARIANT(NOPARAM),                 // VARIANT* Relative         LPVARIANT(NOPARAM),                 // VARIANT* Relationship         LPVARIANT(COleVariant("R")),        // VARIANT* Key         LPVARIANT(COleVariant("First")),    // VARIANT* Text         LPVARIANT(NOPARAM),                 // VARIANT* Image         LPVARIANT(NOPARAM));                // VARIANT* SelectedImage

node = nodes.Add(        LPVARIANT(COleVariant("R")),        // VARIANT* Relative         LPVARIANT(COleVariant( tvwChild ) ),// VARIANT* Relationship         LPVARIANT(COleVariant("C1")),       // VARIANT* Key         LPVARIANT(COleVariant("Child 1")),  // VARIANT* Text         LPVARIANT(NOPARAM),                 // VARIANT* Image         LPVARIANT(NOPARAM));                // VARIANT* SelectedImage

node = nodes.Add(        LPVARIANT(COleVariant("R")),        // VARIANT* Relative         LPVARIANT(COleVariant( tvwChild ) ),// VARIANT* Relationship         LPVARIANT(COleVariant("C2")),       // VARIANT* Key         LPVARIANT(COleVariant("Child 2")),  // VARIANT* Text         LPVARIANT(NOPARAM),                 // VARIANT* Image         LPVARIANT(NOPARAM));                // VARIANT* SelectedImage

node = nodes.Add(        LPVARIANT(NOPARAM),                 // VARIANT* Relative         LPVARIANT(NOPARAM),                 // VARIANT* Relationship         LPVARIANT(COleVariant("S")),        // VARIANT* Key         LPVARIANT(COleVariant("Second")),   // VARIANT* Text         LPVARIANT(NOPARAM),                 // VARIANT* Image         LPVARIANT(NOPARAM));                // VARIANT* SelectedImage

return TRUE; // Return TRUE unless you set the focus to a control. }                        Use ClassWizard to add an OLEDragDrop event handler for the TreeView control. Add the code in OnOLEDragDropTreectrl1 without calling the ConvertXYtoTwips function. The call to HitTest returns NULL if the incorrect x and y values are used.</li></ol>

Additional query words: ocx

Keywords: kbbug kbcmnctrls kbdragdrop kbpending KB200491

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.