비활성화 된 상태의 윈폼!!! 그 안 의 버튼 클릭 이벤트가 한번에 발생하지않습니다..,.......

안녕하세요 현재 윈폼으로 간단한 자동화 프로그램을 개발하고 있습니다.

해당 프로그램은
1 다른 프로세스의 작업 상태를 확인
2 작업이 완료 되면 사용자에게 알림을 전달
3 사용자는 run 기능을 사용하여 최종 결과물을 얻습니다.(여기는 수동)

문제는 3번의 작업 과정에서 발생 하였습니다.
알림은 다른 프로세스에서 전달 받는 것으로 그 과정에서
해달 프로그램의 포커싱을 잃게 되는 것 같습니다.

사용자는 알림을 받고 run 기능을 사용하기 위해
특정 버튼을 클릭 하는데 이때 한번의 클릭으로는 이벤트가 발생하지 않고 있습니다.

이런 문제 경험해 보셨거나 해결방법을 알고 계시면 도움을 좀 주셨으면 합니다.

버튼 누르지 않고 활성화 먼저 주고, 버튼 누르면 이벤트가 발생 하나요?
디버깅 해보시면 감 잡으실 듯 합니다.

1개의 좋아요

답변 감사합니다.

네 그렇게는 하면 문제 없이 버튼 이벤트가 발생 합니다.

저는 비활성화 된 폼에서 버튼을 눌렀을때
바로 버튼 이벤트가 발생하기 원하는데…

어떻게 처리해야 할지 감이 안 오네요.

일반적인 경우 폼에 포커스가 없더라도 일반적인 Button은 클릭 시 이벤트가 발생하는데 다른 요소에 의해 발생하는 문제인 것 같습니다. (혹시 버튼이 ToolStrip이나 DataGridView등에 있는 버튼인지?)
알림을 전달하는 방법 등의 정보가 제공되어야 할 것 같고요, 그리고 WM_처리나 특이사항이 있는 내부 코드가 있는지도 알려주시면 좋을것 같습니다.

혹시 동영상 캡쳐가 가능할까요?

답변 감사합니다.

네 말씀처럼
일반 적인 경우에는 포커스가 없어도 클릭 이벤트가 잘 발생 하더라고요

아마
제가 사용하는 패키지 문제 일수도 있을거 같네요…
MetroModernUI 이고 NuGet 패키지 관리자에서 설치 하였습니다.

아래 이미지 처럼 컨트롤을 배치하고 클릭 테스트를 해보면
라디오버튼도 2번의 클릭으로 체크가 되는 경우도 발생 합니다.

2023-08-03 10 36 02

테스트 환경
vs 2019
Winform
.net framework 4.8
MetroModernUI 설치

메인 폼 코드에 다음 내용을 추가해보세요.

private bool _handleOnClickActivate = false;

protected override void WndProc(ref Message m)
{
    int Low16(IntPtr value) => unchecked((short)GetIntUnchecked(value));
    int GetIntUnchecked(IntPtr value) => 
        IntPtr.Size == 8 ? unchecked((int)value.ToInt64()) : value.ToInt32();

    const int WM_ACTIVATE = 0x0006;
    const int WA_CLICKACTIVE = 0x0002;
    if (m.Msg == WM_ACTIVATE && Low16(m.WParam) == WA_CLICKACTIVE)
    {
        _handleOnClickActivate = true;
    }
    base.WndProc(ref m);
}

protected override void OnActivated(EventArgs e)
{
    base.OnActivated(e);

    if (_handleOnClickActivate)
    {
        var cursorPosition = Cursor.Position;
        var clientPoint = PointToClient(cursorPosition);
        var child = GetChildAtPoint(clientPoint);

        while (child != null)
        {
            if (child is Button button)
            {
                button.PerformClick();
                break;
            }
            else
            {
                clientPoint = child.PointToClient(cursorPosition);
                child = child.GetChildAtPoint(clientPoint);
            }
        }
        _handleOnClickActivate = false;
    }
}

윈도우 메시지를 통해 클릭에 의한 Form Activation을 감지해서 마우스 포인터 위치에 있는 버튼을 찾아 코드로 클릭하는 효과를 주는 코드입니다. (MouseDown 효과는 보이지 않지만 이벤트는 발생합니다.)

참고한 답변: [Solved] WinForm lost focus to another application requires two clicks on toolstrip button - CodeProject

3개의 좋아요

덕분에 문제가 해결된거 같습니다.
이제는 제가 코드를 이해하는 문제만 남았군요 ㅎㅎ

정말 감사합니다.
또 감사합니다.

1개의 좋아요