通过挂钩ExtTextOut提取文本位置

时间:2014-04-18 15:03:16

标签: c++ winapi window easyhook api-hook

我对Windows API RedrawWindowExtTextOut和BitBlt有疑问。 如果我使用参数lprcUpdate = NULL和hrgnUpdate = NULL调用RedrawWindow,我挂钩ExtTextOut来提取屏幕上的文本位置:

 WindowWrapper.RedrawWindow(topWnd, IntPtr.Zero, IntPtr.Zero, RedrawWindowFlags.UpdateNow | RedrawWindowFlags.Frame | RedrawWindowFlags.Invalidate | RedrawWindowFlags.AllChildren | RedrawWindowFlags.Erase);

在钩子函数ExtTextOut中,我调用LPToDP API将位置转换为设备上下文位置。然后它工作正常。文本位置正确。

WindowWrapper.LPtoDP(hdc, arrPoint, 2);

但是,如果我打电话

 WindowWrapper.RedrawWindow(topWnd, ref location, IntPtr.Zero, RedrawWindowFlags.UpdateNow | RedrawWindowFlags.Frame | RedrawWindowFlags.Invalidate | RedrawWindowFlags.AllChildren | RedrawWindowFlags.Erase);

然后它失败了。位置不正确。我看到它通过使用LPToDP转换为错误的位置。

有谁知道这个问题?我们如何解决它?

 public static bool ExtTextOutW_Hook(IntPtr hdc, int X, int Y, uint fuOptions,
                                   IntPtr lprc, [MarshalAs(UnmanagedType.LPWStr)] string lpString,
                                   uint cbCount, IntPtr lpDx)
    {
        try
        {
            lock (IsRetrievingSynch)
            {
                if (IsRetrieving && !string.IsNullOrEmpty(lpString) && cbCount > 0)
                {
                    TextData textData = new TextData();
                    textData.FuncName = "ExtTextOutW";

                    char[] text = new char[cbCount];
                    bool isGlyphIndex = ((fuOptions & 0x0010) == 0x0010);

                    //ETO_GLYPH_INDEX
                    if (isGlyphIndex)
                    {
                        FontMap fontMap = GlyphCharMap.LoadGlyphCharMap(hdc);
                        if (fontMap != null && fontMap.GlyphCharMap != null)
                        {
                            for (int i = 0; i < cbCount; i++)
                            {
                                ushort glyph = lpString[i];
                                if (glyph < fontMap.GlyphCharMap.Length)
                                {
                                    if (fontMap.GlyphCharMap[glyph] != 0)
                                    {
                                        text[i] = (char)(fontMap.GlyphCharMap[glyph]);
                                    }
                                    else
                                    {
                                        text[i] = (char)32;                                           
                                    }
                                }
                                else
                                {
                                    text[i] = (char)glyph;                                        
                                }                                  
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < cbCount; i++)
                        {
                            text[i] = lpString[i];
                        }
                    }

                    textData.Text = new string(text);
                    textData.Text = textData.Text.Normalize(NormalizationForm.FormKC);
                    //textData.Text = textData.Text.Trim();

                    if (!string.IsNullOrEmpty(textData.Text))
                    {
                        int realCount = textData.Text.Length;

                        TEXTMETRICW tm = new TEXTMETRICW();
                        WindowWrapper.GetTextMetricsW(hdc, out tm);
                        int[] nWidth = new int[1];
                        WindowWrapper.GetCharWidth32W(hdc, ' ', ' ', nWidth);
                        textData.CharHeight = tm.tmHeight;
                        textData.CharWidth = nWidth[0];
                        textData.CharWidths = new int[realCount];
                        for (int i = 0; i < realCount; i++)
                        {
                            nWidth = new int[1];
                            WindowWrapper.GetCharWidth32W(hdc, textData.Text[i], textData.Text[i], nWidth);
                            textData.CharWidths[i] = nWidth[0];
                        }

                        uint textAlign = WindowWrapper.GetTextAlign(hdc);
                        POINT ptStartPos = new POINT();


                        if ((textAlign & WindowWrapper.TA_UPDATECP) > 0)
                        {
                            WindowWrapper.GetCurrentPositionEx(hdc, out ptStartPos);
                        }
                        else
                        {
                            ptStartPos.X = X;
                            ptStartPos.Y = Y;
                        }                            

                        switch (textAlign & (WindowWrapper.TA_BASELINE | WindowWrapper.TA_BOTTOM | WindowWrapper.TA_TOP))
                        {
                            case WindowWrapper.TA_BOTTOM:
                                textData.Location.Top = Y - tm.tmHeight;
                                textData.Location.Bottom = Y;
                                break;
                            case WindowWrapper.TA_BASELINE:
                                textData.Location.Top = Y - tm.tmAscent;
                                textData.Location.Bottom = Y + tm.tmDescent;
                                break;
                            case WindowWrapper.TA_TOP:
                            default:
                                textData.Location.Top = Y;
                                textData.Location.Bottom = Y + tm.tmHeight;
                                break;
                        }

                        int nLAlign = 0, nRAlign = 0;
                        switch (textAlign & (WindowWrapper.TA_LEFT | WindowWrapper.TA_RIGHT | WindowWrapper.TA_CENTER))
                        {
                            case WindowWrapper.TA_LEFT:
                                nLAlign = 0;
                                nRAlign = 2;
                                break;
                            case WindowWrapper.TA_CENTER:
                                nLAlign = -1;
                                nRAlign = 1;
                                break;
                            case WindowWrapper.TA_RIGHT:
                                nLAlign = -2;
                                nRAlign = 0;
                                break;
                        }

                        SIZE size = new SIZE();
                        if (WindowWrapper.GetTextExtentPoint32W(hdc, lpString, (int)cbCount, ref size))
                        {
                            textData.Location.Left = X + nLAlign * (size.CX / 2);                                
                            textData.Location.Right = X + nRAlign * (size.CX / 2);                                
                        }
                        else
                        {
                            textData.Location.Left = X - 20;                              
                            textData.Location.Right = X + 20;                                
                        }
                        LogFactory.RemoteLog.TraceDebug(string.Format("1.ExtTextOutW {0} {1} {2} {3} {4}",
                            textData.Text, textData.Location.Left, textData.Location.Top, 
                            textData.Location.Right - textData.Location.Left, 
                            textData.Location.Bottom - textData.Location.Top));

                        //Utility.ClipViewPort(hdc, ref textData.Location);


                        POINT[] arrPoint = new POINT[2];
                        arrPoint[0] = new POINT()
                        {
                            X = textData.Location.Left,
                            Y = textData.Location.Top
                        };
                        arrPoint[1] = new POINT()
                        {
                            X = textData.Location.Right,
                            Y = textData.Location.Bottom
                        };
                        POINT ptDCOrg = new POINT();

                        WindowWrapper.LPtoDP(hdc, arrPoint, 2);

                        textData.Location.Left = arrPoint[0].X;
                        textData.Location.Top = arrPoint[0].Y;
                        textData.Location.Right = arrPoint[1].X;
                        textData.Location.Bottom = arrPoint[1].Y;

                        WindowWrapper.GetDCOrgEx(hdc, out ptDCOrg);
                        textData.Location.Left += ptDCOrg.X;
                        textData.Location.Top += ptDCOrg.Y;
                        textData.Location.Right += ptDCOrg.X;
                        textData.Location.Bottom += ptDCOrg.Y;

                        LogFactory.RemoteLog.TraceDebug(string.Format("2.ExtTextOutW {0} {1} {2} {3} {4}",
                            textData.Text, textData.Location.Left, textData.Location.Top,
                            textData.Location.Right - textData.Location.Left,
                            textData.Location.Bottom - textData.Location.Top));

                        StringBuilder fontName = new StringBuilder();
                        fontName.Capacity = 260;
                        WindowWrapper.GetTextFace(hdc, 260, fontName);
                        textData.Font = fontName.ToString();

                        IntPtr hWnd = WindowWrapper.WindowFromDC(hdc);
                        if (WindowWrapper.IsWindowVisible(hWnd))
                        {
                            textData.Hdc = hdc;
                            textData.Hwnd = hWnd;

                            textData.ZOrder = WindowWrapper.GetZOrder(hWnd);

                            if (Utility.IsIntersect(_location, textData.Location) && WindowWrapper.IsChildWindow(_topWindow, hWnd))
                            {
                                LogFactory.RemoteLog.TraceVerbose(string.Format("3.ExtTextOutW {0} {1} {2} {3} {4} Z-Order: {5}",
                                    textData.Text, 
                                    textData.Location.Left, 
                                    textData.Location.Top, 
                                    textData.Location.Right - textData.Location.Left,
                                    textData.Location.Bottom - textData.Location.Top, 
                                    textData.ZOrder));
                                if (TextDataChannel != null)
                                    TextDataChannel.SendTextData(textData);
                            }
                        }
                        else
                        {
                            textData.Hdc = hdc;
                            //if (lpDx != IntPtr.Zero)
                            //    Utility.ClipViewPort(hdc, ref textData.Location);
                            _tempDataList.Add(textData);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            LogFactory.RemoteLog.TraceError("ExtTextOutW " + ex.Message);
        }

        return ExtTextOutW(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx);
    }

感谢。

0 个答案:

没有答案