대략 1년 후... 2부를 쓰게됩니다. 게으름의 극치를 보여주는군요....ㅋㅋㅋ


이번 글에서는 카카오톡이 켜져있는지의 여부를 확인하는 방법, 열린 채팅방 목록을 가져오는 것,

그리고 채팅방에 텍스트를 입력/전송하는 것을 설명함으로써 마치려고 합니다.


만약, 1부를 읽지 않으셨다면 "" 1부를 읽고 와주시면 좋겠어요!

> 카카오톡 파헤치기 - 1부 


1부에서는 설명드리지 않았는데, 카카오톡의 클래스 구조는 다음 그림에서 확인하실 수 있습니다.    


위 그림을 트리 구조로 표현하면 다음과 같이 표현할 수 있습니다.

+ #32770

+ #32770

+ #32770

- Edit

+ EVA_VH_ListControl

- _EVA_CustomScrollCtrl

+ EVA_VH_ListControl

- _EVA_CustomScrollCtrl

+ #32770

- Edit

+ EVA_VH_ListControl

- _EVA_CustomScrollCtrl

+ EVA_VH_ListControl

- _EVA_CustomScrollCtrl

+ EVA_Windowㅋ

- _EVA_CustomScrollCtrl

+ EVA_Window

- _EVA_CustomScrollCtrl

+ #32770

- Edit

- EVA_Window


이 구조를 응용하면, 카카오톡이 실행 중인지 아닌지를 확인할 수 있게 됩니다.

카카오톡이 실행 중인지 확인하는 방법

  1. 의사 코드 (Pseudo code)
    1. FindWindow/FindWindowEx API를 사용하여 클래스 이름이 #32770 인 윈도우를 찾는다.
    2. GetWindowText API를 사용하여 해당 윈도우의 텍스트를 가져온다.
      1. API가 실패한 경우 다음 윈도우로 넘어간다.
    3. 해당 윈도우의 텍스트가 "카카오톡" 인 경우 FindWindowEx API를 사용하여 구조를 확인한다.

  2. 실제 코드 (C#)
  3. 카카오톡이 실행 중인지 확인하는 방법 (C#)
    public static bool IsValidKakaotalkWindow(IntPtr hWnd) {
        // 창 핸들인지 확인한다.
        if (!IsWindow(hWnd)) return false;

        // 윈도우의 제목을 가져온다.
        string name = GetWindowText(hWnd);
        if (name == null) return false;

        // 총 2개의 하위 다이얼로그가 있으므로
        // 핸들을 가져온다.
        IntPtr hChildDialog1 = FindWindowEx(hWnd, IntPtr.Zero, "#32770", null);
        IntPtr hChildDialog2 = FindWindowEx(hWnd, hChildDialog1, "#32770", null);

        // 두 개의 다이얼로그 중 하나의 값이라도 받아오지 못한 경우
        // 정상적인 카카오톡 창이 아니다.
        if (hChildDialog1 == IntPtr.Zero || hChildDialog2 == IntPtr.Zero) return false;

        // 이제 다이얼로그의 하위 구조를 확인한다.
        IntPtr hDialogChildDialog1 = FindWindowEx(hChildDialog1, IntPtr.Zero, "#32770", null);
        IntPtr hDialogChildDialog2 = FindWindowEx(hChildDialog1, hDialogChildDialog1, "#32770", null);
        IntPtr hDialogChildEvaWindow1 = FindWindowEx(hChildDialog1, IntPtr.Zero, "EVA_Window", null);
        IntPtr hDialogChildEvaWindow2 = FindWindowEx(hChildDialog1, hDialogChildEvaWindow1, "EVA_Window", null);

        // 네 개의 윈도우 핸들이 유효하다면 정상적인 카카오톡 창이다.
        // 더 깊게 들어가야 하지만, 이 정도만 검사하면 된다.
        return
            hDialogChildDialog1 != IntPtr.Zero &&
            hDialogChildDialog2 != IntPtr.Zero &&
            hDialogChildEvaWindow1 != IntPtr.Zero &&
            hDialogChildEvaWindow2 != IntPtr.Zero;
    }


열린 채팅방을 가져오는 방법은 더 쉽습니다. 위 코드를 약간 응용하기만 하면 되는데요,

본격적으로 들어가기에 앞서 1부에서 보여드렸던 카카오톡 채팅방 구조를 슬쩍 보시고 넘어가면 되겠습니다.



채팅방 구조를 트리 구조로 표현하면 다음과 같이 표현할 수 있습니다.

+ #32770

+ EVA_VH_ListControl

- _EVA_CustomScrollCtrl

- RichEdit20W


이 구조를 이해하시면 지정된 다이얼로그가 채팅방인지 아닌지 아주 손쉽게 검사할 수 있게 됩니다.

카카오톡 채팅방인지 아닌지 검사하는 방법

  1. 의사 코드 (Pseudo code)
    1. FindWindow/FindWindowEx API를 사용하여 클래스 이름이 #32770 인 윈도우를 찾는다.
    2. FindWindowEx API를 사용하여 1단계에서 찾은 #32770 핸들의 자식 핸들을 찾는다.
      1. 찾는 클래스 이름은 각각 RichEdit20W / EVA_VH_ListControl
      2. EVA_VH_ListControl 핸들을 찾은 다음에는 _EVA_CustomScrollCtrl 핸들을 찾으면 된다.

  2. 실제 코드 (C#)
  3. 카카오톡 채팅방인지 확인하는 방법 (C#)
    public static bool IsValidChatWindow(IntPtr hWnd) {
        if (!IsWindow(hWnd)) return false;

        IntPtr hEdit, hList, hScrl;
        hEdit = FindWindowEx(hWnd, IntPtr.Zero, "RichEdit20W", null);
        hList = FindWindowEx(hWnd, IntPtr.Zero, "EVA_VH_ListControl", null);
        hScrl = FindWindowEx(hList, IntPtr.Zero, "_EVA_CustomScrollCtrl", null);
        return (hEdit != IntPtr.Zero) && (hList != IntPtr.Zero) && (hScrl != IntPtr.Zero);
    }


카카오톡 윈도우인지 확인하는 방법과 카카오톡 채팅방인지 확인하는 방법은 모두 설명드렸습니다.

이제 마지막 남은 RichEdit20W 컨트롤에 텍스트를 설정하고 전송하는 방법을 설명해 드리도록 하겠습니다.


어떻게 보면 텍스트를 설정/전송하는 것이 가장 쉽게 느껴지실 수도 있습니다.

SendMessage API를 이용하여 RichEdit20W 컨트롤에 텍스트를 설정한 후 PostMessage API로 키 입력을 시뮬레이션하면 ~~끝!

카카오톡 채팅방에 텍스트 설정/전송하는 방법

  1. 의사 코드 (Pseudo code)
    1. SendMessage API와 WM_SETTEXT 메세지를 이용하여 RichEdit20W 컨트롤에 텍스트를 설정
    2. PostMessage API와 WM_KEYDOWN, WM_KEYUP 메세지를 이용하여 키 입력을 시뮬레이션함

  2. 실제 코드 (C#)
  3. 카카오톡 채팅방에 텍스트 설정/전송하는 방법 (C#)
    public static void SendText(IntPtr hEdit) {
        SendMessage(hEdit, WM_SETTEXT, IntPtr.Zero, text);
        PostMessage(hEdit, WM_KEYDOWN, VK_ENTER, IntPtr.Zero);
        PostMessage(hEdit, WM_KEYUP, VK_ENTER, IntPtr.Zero);
    }


코드가 간단한 순서는 텍스트 전송 > 채팅방 확인 > 카카오톡 확인 순이네요.

하지만 코드 하나하나가 복잡하지 않기 때문에 이해하시기도 쉬울 것 같습니다.

단, 주의하실 점은 플랫폼 호출(P/Invoke)에 대한 이해도가 어느 정도 있으셔야 합니다.


코드를 무작정 복/붙 하시고 "SendMessage 같은 함수는 어디있나요?" 라고 물으시는 분이 없으셨으면 좋겠습니다.

(불법적인 목적이 아닌 공부 목적으로만 사용하셨으면 좋겠습니다)


+ Recent posts