Информация об изменениях

Сообщение Re[2]: Кликнуть в скрытое окно от 06.08.2019 4:48

Изменено 06.08.2019 5:06 Cannol

Re[2]: Кликнуть в скрытое окно
Бесполезно, не фурычит.

Если кому вдруг интересно, привожу ниже код.
Вот так создаю окно:

//hWndMain = CreateWindowEx(WS_EX_TOPMOST, szWndClassMain, szWndTitleMain, WS_OVERLAPPEDWINDOW, dwWndX, dwWndY, wWndWidth, wWndHeight, NULL, NULL, hInst, NULL);
hWndMain = CreateWindowEx(WS_EX_TRANSPARENT, szWndClassMain, szWndTitleMain, WS_OVERLAPPEDWINDOW, dwWndX, dwWndY, wWndWidth, wWndHeight, NULL, NULL, hInst, NULL);


А вот 2 ключевые функции:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool GrabTheScreen()
{
    RECT rc;
    HWND hwnd = FindWindow(szWndClassMain, NULL);    //the window can't be min
    if (hwnd == NULL)
    {
        Write2Log(fpLogFile, "Error: window not found.\n");
        return false;
    }
    GetClientRect(hwnd, &rc);

    //create
    HDC hdcScreen = GetDC(NULL);
    HDC hdc = CreateCompatibleDC(hdcScreen);
    HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, rc.right - rc.left, rc.bottom - rc.top);
    SelectObject(hdc, hbmp);

// Code to debug:
if (byCodeOption <= 100)
ShowWindow(hwnd, SW_SHOWNOACTIVATE);
//SetForegroundWindow(hwnd);
else if (byCodeOption > 100)
{
DWORD dwStyle=GetWindowLong(hwnd, GWL_STYLE);
SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle | WS_VISIBLE); // SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_VISIBLE);
}

    //Print to memory hdc
    PrintWindow(hwnd, hdc, PW_CLIENTONLY);

// Code to debug:
if (byCodeOption <= 100)
ShowWindow(hwnd, SW_HIDE);

    pCockpit->setBitmap(hbmp); // m_pRT->CreateBitmap(...)

    //release
    DeleteDC(hdc);
    DeleteObject(hbmp);
    ReleaseDC(NULL, hdcScreen);

    Write2Log(fpLogFile, "Image grabbed successfully!\n");

    return true;
} // GrabTheScreen

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool EFB::ProcessTheMouseClick(PPIXPOINT relative_point, WebBrowser *pWebBrowser)
{
    POINT ptOld;                // previous cursor location 
    GetCursorPos(&ptOld);

    IOleInPlaceFrame *pFrame;
    IOleInPlaceUIWindow *pDoc;
    RECT prcPosRect;
    RECT prcClipRect;
    tagOIFI pFrameInfo;
    pFrameInfo.cb = sizeof(tagOIFI);
    HRESULT hr = pWebBrowser->GetWindowContext(&pFrame, &pDoc, &prcPosRect, &prcClipRect, &pFrameInfo);

    HWND hwnd = pFrameInfo.hwndFrame;
    RECT rcClip;           // new area for ClipCursor
    RECT rcOldClip;        // previous area for ClipCursor
    GetClipCursor(&rcOldClip); // Record the area in which the cursor can move. 
    GetWindowRect(hwnd, &rcClip); // Get the dimensions of the application's window. 
// Code to debug:
static bool bClipCursor = true;
if (bClipCursor)
    ClipCursor(&rcClip); // Confine the cursor to the application's window. 

    // 
    // Process input from the confined cursor.
    //
    POINT pt;
    const int nSizeX = rcClip.right - rcClip.left;
    const int nSizeY = rcClip.bottom - rcClip.top;
    int nRelX = Round(((double) relative_point->x / m_wGaugeWidth) * nSizeX) + rcClip.left;
    int nRelY = Round(((double) relative_point->y / m_wGaugeHeight) * nSizeY) + rcClip.top;
    Write2Log(fpLogFile, "PPIXPOINT: [%d*%d]=>[%d*%d].\n", relative_point->x, relative_point->y, nRelX, nRelY);

    pt.x = nRelX;
    pt.y = nRelY;

// Code to debug:
static BYTE byShowTheWnd = 0;
if (byCodeOption > 100)
{
//static int PosX = 30000;
//static int PosY = PosX;
//static UINT uFlags = SWP_NOSIZE;
//SetWindowPos(hwnd, HWND_TOP, PosX, PosY, nSizeX, nSizeY, uFlags);

DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle | WS_VISIBLE); // SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_VISIBLE);
}
else if (byShowTheWnd == 0)
ShowWindow(hwnd, SW_SHOWNORMAL);
else if (byShowTheWnd == 1)
ShowWindow(hwnd, SW_SHOWNOACTIVATE);

// Code to debug:
static BYTE byForegroundFuncAlt = 1;
if (byForegroundFuncAlt == 1)
//SetForegroundWindow(hwnd);
SetActiveWindow(hwnd);
else if (byForegroundFuncAlt == 2)
{
static int PosX = -3000;
static int PosY = PosX;
static UINT uFlags = 0;
//SetWindowPos(hwnd, HWND_NOTOPMOST, PosX, PosY, nSizeX, nSizeY, uFlags);
SetWindowPos(hwnd, HWND_TOP, PosX, PosY, nSizeX, nSizeY, uFlags);
}
    SetCursorPos(pt.x, pt.y);
    // 
    // Process mouse button press.
    //

// Code to debug:
if (byCodeOption == 0 || byCodeOption == 101)
{
    INPUT input={0};
    // left down
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN; // mouse button down
    SendInput(1,&input,sizeof(INPUT)); //call SendInput, pass in input to click
    Sleep(1);
    // left up
    ZeroMemory(&input,sizeof(INPUT)); //clear out input
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_LEFTUP; // mouse button up
    SendInput(1,&input,sizeof(INPUT)); //call SendInput, pass in input to unclick
/*
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
*/
}
else if (byCodeOption == 2)
{
    // Option B1
    SendMessage(hwnd, WM_LBUTTONDOWN, pt.x, pt.y);
    Sleep(10);
    SendMessage(hwnd, WM_LBUTTONUP, pt.x, pt.y);
}
else if (byCodeOption == 4)
{
    // Option B2
    SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
    Sleep(10);
    SendMessage(hwnd, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
}
else if (byCodeOption == 6)
{
    // Option C1
    PostMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
    Sleep(5);
    PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
}
else if (byCodeOption == 8)
{
    // Option C2
    PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
    Sleep(5);
    PostMessage(hwnd, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
}
else if (byCodeOption == 10)
{
    // Option C3
    PostMessage(hwnd, WM_LBUTTONDOWN, pt.x, pt.y);
    Sleep(5);
    PostMessage(hwnd, WM_LBUTTONUP, pt.x, pt.y);
}
else if (byCodeOption == 100)
{
    CString Name;
    CPoint CursorPos;
    GetCursorPos(&CursorPos);
    IAccessiblePtr pIAcc;
    _variant_t vt;
    BSTR pName = NULL; BSTR pValue = NULL;

    //assert((pt.x == CursorPos.x) && (pt.y == CursorPos.y));
    if (!((pt.x == CursorPos.x) && (pt.y == CursorPos.y)))
    {
        Write2Log(fpLogFile, "Cursor out or range: [%d,%d] vs [%d,%d].\n", CursorPos.x, CursorPos.y, pt.x, pt.y);

        static bool bUseAnotherCoords = false;
        if (bUseAnotherCoords)
        {
            CursorPos.x = pt.x;
            CursorPos.y = pt.y;
        }
    }

    HRESULT hr;
    static bool bAccessCursor = true;
    if (bAccessCursor)
        hr = AccessibleObjectFromPoint(CursorPos, &pIAcc, &vt);
    else
        hr = AccessibleObjectFromWindow(hwnd, OBJID_CURSOR, IID_IAccessible, (void **) &pIAcc);
    if (SUCCEEDED(hr))
    {
        VARIANT varChild;
        hr = pIAcc->accHitTest(pt.x, pt.y, &varChild);
        //if ((hr == S_OK) && (varChild.lVal != CHILDID_SELF))
        //{
        //    hr = pIAcc->accSelect((SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION), varChild);
        //}

        {
            //pIAcc->get_accChild(
            BSTR pName = NULL;
            hr = pIAcc->get_accName(vt, &pName);
            if (SUCCEEDED(hr))
            {
                if (pName && ::SysStringLen(pName))
                    Name = pName;

                VARIANT varId;
                varId.vt = VT_I4;
                varId.lVal = CHILDID_SELF;
                hr = pIAcc->accDoDefaultAction(varId);
                if (SUCCEEDED(hr))
                    Write2Log(fpLogFile, "Webbrowser DoAction OK: '%s'.\n", Name.Left(200));
                else
                    //Write2Log(fpLogFile, "Webbrowser DoAction failed: %05s, 0x%X.\n", Name.GetBuffer(), hr);
                    Write2Log(fpLogFile, "Webbrowser DoAction failed: '%s', 0x%X.\n", Name.Left(200), hr);

                ::SysFreeString(pName);
            }
        }
    }
}

    ClipCursor(&rcOldClip); // Restore the cursor to its previous area.
    SetCursorPos(ptOld.x, ptOld.y); // Restore previous coordinates of the cursor.

// Code to debug:
static bool bHideWnd = false;
if (bHideWnd)
ShowWindow(hwnd, SW_HIDE);

    return true;
} // ProcessTheMouseClick


Как тут видно, перепробовал разные варианты (закомментированные, через static, через "else if (byCodeOption == ***)", и т.д.).
В том числе попробовал посоветованные выше IAccessible, SetWindowLong() и сильно отрицательные координаты. Что-то ничто не помогает.
Теперь уже буду пробовать другие упомянутые выше советы, типа Sciter.

Здравствуйте, CEMb, Вы писали:
CEM>Гипотеза: процесс окна проверяет у себя WS_VISIBLE.
Там стандартнейший и простейший IWebBrowser2 (этот проект), я несколько сомневаюсь, что там есть такое. Но таки да, подозрения эти обоснованы!
Тем не менее SetWindowLong() тоже не помог. Может, я где-то накосячил в другом месте.
Re[2]: Кликнуть в скрытое окно
Бесполезно, не фурычит.
Если кому вдруг интересно, привожу ниже код.
Вот так создаю окно:

//hWndMain = CreateWindowEx(WS_EX_TOPMOST, szWndClassMain, szWndTitleMain, WS_OVERLAPPEDWINDOW, dwWndX, dwWndY, wWndWidth, wWndHeight, NULL, NULL, hInst, NULL);
hWndMain = CreateWindowEx(WS_EX_TRANSPARENT, szWndClassMain, szWndTitleMain, WS_OVERLAPPEDWINDOW, dwWndX, dwWndY, wWndWidth, wWndHeight, NULL, NULL, hInst, NULL);


А вот 2 ключевые функции:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool GrabTheScreen()
{
    RECT rc;
    HWND hwnd = FindWindow(szWndClassMain, NULL);    //the window can't be min
    if (hwnd == NULL)
    {
        Write2Log(fpLogFile, "Error: window not found.\n");
        return false;
    }
    GetClientRect(hwnd, &rc);

    //create
    HDC hdcScreen = GetDC(NULL);
    HDC hdc = CreateCompatibleDC(hdcScreen);
    HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, rc.right - rc.left, rc.bottom - rc.top);
    SelectObject(hdc, hbmp);

// Code to debug:
if (byCodeOption <= 100)
ShowWindow(hwnd, SW_SHOWNOACTIVATE);
//SetForegroundWindow(hwnd);
else if (byCodeOption > 100)
{
DWORD dwStyle=GetWindowLong(hwnd, GWL_STYLE);
SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle | WS_VISIBLE); // SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_VISIBLE);
}

    //Print to memory hdc
    PrintWindow(hwnd, hdc, PW_CLIENTONLY);

// Code to debug:
if (byCodeOption <= 100)
ShowWindow(hwnd, SW_HIDE);

    pTablet->setBitmap(hbmp); // m_pRT->CreateBitmap(...)

    //release
    DeleteDC(hdc);
    DeleteObject(hbmp);
    ReleaseDC(NULL, hdcScreen);

    Write2Log(fpLogFile, "Image grabbed successfully!\n");

    return true;
} // GrabTheScreen

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool EFB::ProcessTheMouseClick(PPIXPOINT relative_point, WebBrowser *pWebBrowser)
{
    POINT ptOld;                // previous cursor location 
    GetCursorPos(&ptOld);

    IOleInPlaceFrame *pFrame;
    IOleInPlaceUIWindow *pDoc;
    RECT prcPosRect;
    RECT prcClipRect;
    tagOIFI pFrameInfo;
    pFrameInfo.cb = sizeof(tagOIFI);
    HRESULT hr = pWebBrowser->GetWindowContext(&pFrame, &pDoc, &prcPosRect, &prcClipRect, &pFrameInfo);

    HWND hwnd = pFrameInfo.hwndFrame;
    RECT rcClip;           // new area for ClipCursor
    RECT rcOldClip;        // previous area for ClipCursor
    GetClipCursor(&rcOldClip); // Record the area in which the cursor can move. 
    GetWindowRect(hwnd, &rcClip); // Get the dimensions of the application's window. 
// Code to debug:
static bool bClipCursor = true;
if (bClipCursor)
    ClipCursor(&rcClip); // Confine the cursor to the application's window. 

    // 
    // Process input from the confined cursor.
    //
    POINT pt;
    const int nSizeX = rcClip.right - rcClip.left;
    const int nSizeY = rcClip.bottom - rcClip.top;
    int nRelX = Round(((double) relative_point->x / m_wGaugeWidth) * nSizeX) + rcClip.left;
    int nRelY = Round(((double) relative_point->y / m_wGaugeHeight) * nSizeY) + rcClip.top;
    Write2Log(fpLogFile, "PPIXPOINT: [%d*%d]=>[%d*%d].\n", relative_point->x, relative_point->y, nRelX, nRelY);

    pt.x = nRelX;
    pt.y = nRelY;

// Code to debug:
static BYTE byShowTheWnd = 0;
if (byCodeOption > 100)
{
//static int PosX = 30000;
//static int PosY = PosX;
//static UINT uFlags = SWP_NOSIZE;
//SetWindowPos(hwnd, HWND_TOP, PosX, PosY, nSizeX, nSizeY, uFlags);

DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle | WS_VISIBLE); // SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_VISIBLE);
}
else if (byShowTheWnd == 0)
ShowWindow(hwnd, SW_SHOWNORMAL);
else if (byShowTheWnd == 1)
ShowWindow(hwnd, SW_SHOWNOACTIVATE);

// Code to debug:
static BYTE byForegroundFuncAlt = 1;
if (byForegroundFuncAlt == 1)
//SetForegroundWindow(hwnd);
SetActiveWindow(hwnd);
else if (byForegroundFuncAlt == 2)
{
static int PosX = -3000;
static int PosY = PosX;
static UINT uFlags = 0;
//SetWindowPos(hwnd, HWND_NOTOPMOST, PosX, PosY, nSizeX, nSizeY, uFlags);
SetWindowPos(hwnd, HWND_TOP, PosX, PosY, nSizeX, nSizeY, uFlags);
}
    SetCursorPos(pt.x, pt.y);
    // 
    // Process mouse button press.
    //

// Code to debug:
if (byCodeOption == 0 || byCodeOption == 101)
{
    INPUT input={0};
    // left down
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN; // mouse button down
    SendInput(1,&input,sizeof(INPUT)); //call SendInput, pass in input to click
    Sleep(1);
    // left up
    ZeroMemory(&input,sizeof(INPUT)); //clear out input
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_LEFTUP; // mouse button up
    SendInput(1,&input,sizeof(INPUT)); //call SendInput, pass in input to unclick
/*
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
*/
}
else if (byCodeOption == 2)
{
    // Option B1
    SendMessage(hwnd, WM_LBUTTONDOWN, pt.x, pt.y);
    Sleep(10);
    SendMessage(hwnd, WM_LBUTTONUP, pt.x, pt.y);
}
else if (byCodeOption == 4)
{
    // Option B2
    SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
    Sleep(10);
    SendMessage(hwnd, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
}
else if (byCodeOption == 6)
{
    // Option C1
    PostMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
    Sleep(5);
    PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
}
else if (byCodeOption == 8)
{
    // Option C2
    PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
    Sleep(5);
    PostMessage(hwnd, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
}
else if (byCodeOption == 10)
{
    // Option C3
    PostMessage(hwnd, WM_LBUTTONDOWN, pt.x, pt.y);
    Sleep(5);
    PostMessage(hwnd, WM_LBUTTONUP, pt.x, pt.y);
}
else if (byCodeOption == 100)
{
    CString Name;
    CPoint CursorPos;
    GetCursorPos(&CursorPos);
    IAccessiblePtr pIAcc;
    _variant_t vt;
    BSTR pName = NULL; BSTR pValue = NULL;

    //assert((pt.x == CursorPos.x) && (pt.y == CursorPos.y));
    if (!((pt.x == CursorPos.x) && (pt.y == CursorPos.y)))
    {
        Write2Log(fpLogFile, "Cursor out or range: [%d,%d] vs [%d,%d].\n", CursorPos.x, CursorPos.y, pt.x, pt.y);

        static bool bUseAnotherCoords = false;
        if (bUseAnotherCoords)
        {
            CursorPos.x = pt.x;
            CursorPos.y = pt.y;
        }
    }

    HRESULT hr;
    static bool bAccessCursor = true;
    if (bAccessCursor)
        hr = AccessibleObjectFromPoint(CursorPos, &pIAcc, &vt);
    else
        hr = AccessibleObjectFromWindow(hwnd, OBJID_CURSOR, IID_IAccessible, (void **) &pIAcc);
    if (SUCCEEDED(hr))
    {
        VARIANT varChild;
        hr = pIAcc->accHitTest(pt.x, pt.y, &varChild);
        //if ((hr == S_OK) && (varChild.lVal != CHILDID_SELF))
        //{
        //    hr = pIAcc->accSelect((SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION), varChild);
        //}

        {
            //pIAcc->get_accChild(
            BSTR pName = NULL;
            hr = pIAcc->get_accName(vt, &pName);
            if (SUCCEEDED(hr))
            {
                if (pName && ::SysStringLen(pName))
                    Name = pName;

                VARIANT varId;
                varId.vt = VT_I4;
                varId.lVal = CHILDID_SELF;
                hr = pIAcc->accDoDefaultAction(varId);
                if (SUCCEEDED(hr))
                    Write2Log(fpLogFile, "Webbrowser DoAction OK: '%s'.\n", Name.Left(200));
                else
                    //Write2Log(fpLogFile, "Webbrowser DoAction failed: %05s, 0x%X.\n", Name.GetBuffer(), hr);
                    Write2Log(fpLogFile, "Webbrowser DoAction failed: '%s', 0x%X.\n", Name.Left(200), hr);

                ::SysFreeString(pName);
            }
        }
    }
}

    ClipCursor(&rcOldClip); // Restore the cursor to its previous area.
    SetCursorPos(ptOld.x, ptOld.y); // Restore previous coordinates of the cursor.

// Code to debug:
static bool bHideWnd = false;
if (bHideWnd)
ShowWindow(hwnd, SW_HIDE);

    return true;
} // ProcessTheMouseClick


Как тут видно, перепробовал разные варианты (закомментированные, через static, через "else if (byCodeOption == ***)", и т.д.).
В том числе попробовал посоветованные выше IAccessible, SetWindowLong() и сильно отрицательные координаты. Что-то ничто не помогает.
Теперь уже буду пробовать другие упомянутые выше советы, типа Sciter. Вообще сторонние либы я не очень-то хотел, ибо там обычно заморочки с лицензированием.


Здравствуйте, CEMb, Вы писали:
CEM>Гипотеза: процесс окна проверяет у себя WS_VISIBLE.
Там стандартнейший и простейший IWebBrowser2 (этот проект), я несколько сомневаюсь, что там есть такое. Но таки да, подозрения эти обоснованы!
Тем не менее SetWindowLong() тоже не помог. Может, я где-то накосячил в другом месте.


ЗЫ. Нагуглил еще AttachThreadInput() ("Функция AttachThreadInput подключает или отключает механизм обработки ввода данных одного из потоков к механизму другого потока.") Кажется, тоже есть смысл попробовать. Создать для того скрытого окна отдельный поток и продублировать туда сообщения из основного 3D приложения. Опять же не факт, что таким макаром сообщения таки будут приходить туда.