HJSoft

카톡 자동발송에 이은 - '내용 수집' 자동화

HJSoft 맞춤형솔루션 2026. 1. 24. 11:32

https://m-hjsoft.tistory.com/54

 

💬 C# WinForms + AutoHotkey를 활용한 메시지 자동 입력 예제

🔧 참고한 자료 엑셀 카카오톡 자동화프로그램만들기(윈도우API응용) - 오빠두엑셀 : 강의 인상적으로 봤습니다 감사합니다.​AutoHotkey와 Excel을 연동하여 구현한 예제를 보고 VB소스를 > C# WinForm

m-hjsoft.tistory.com

 

 

자동 발송에 이어 내용수집


※ 본 게시물은 비상업적 목적의 기술 공유입니다.

오직 개인 학습과 테스트를 위한 코드입니다.

🛠️ 개발환경

  • C# .NET WinForm (.NET Framework 4.7 이상)
  • AutoHotkey.Interop (NuGet 패키지 설치 또는 직접 DLL 참조)
  • Windows 10/11
  • 카카오톡 PC 버전

자동 발송에 이어

① 대화방 찾기 → ② 대화방 띄우기 → ③ 대화 내용 추출

① 첫번째리스트 → ② 대화방 띄우기 → ③ 대화 내용 추출

 

 


        private void button3_Click(object sender, EventArgs e)
        {
            string target = textBox1.Text;
            
            if (string.IsNullOrWhiteSpace(target))
            {
                MessageBox.Show("대화방 이름을 입력하세요.");
                return;
            }

            ActiveChat(target, 1000, true);

            IntPtr hwndKakaoTalk = FindTopWindowByTitleContains(target);
            if (hwndKakaoTalk == IntPtr.Zero)
            {
                MessageBox.Show("대화창을 찾을 수 없습니다.");
                return;
            }

            string content = ReadChatContent(hwndKakaoTalk, 250);
            if (string.IsNullOrWhiteSpace(content))
            {
                MessageBox.Show("대화 내용을 읽지 못했습니다.");
                return;
            }

            textBox3.Text = content;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            IntPtr hwndMain = FindHwndEVA();
            if (hwndMain == IntPtr.Zero)
            {
                MessageBox.Show("카카오톡 메인창을 찾을 수 없습니다.");
                return;
            }

            IntPtr roomList = FindRoomListWindow(hwndMain);
            if (roomList == IntPtr.Zero)
            {
                MessageBox.Show("대화 리스트를 찾을 수 없습니다.");
                return;
            }

            RECT rect;
            if (!GetWindowRect(roomList, out rect))
            {
                MessageBox.Show("대화 리스트 위치를 읽지 못했습니다.");
                return;
            }

            int width = rect.Right - rect.Left;
            int clickX = rect.Left + Math.Min(width - 10, Math.Max(120, width / 4));
            int clickY = rect.Top + 35;

            SetForegroundWindow(hwndMain);
            Thread.Sleep(120);
            DoubleClickAt(clickX, clickY);

            IntPtr chatWindow = FindRecentChatWindow();
            if (chatWindow == IntPtr.Zero)
            {
                MessageBox.Show("대화창을 찾을 수 없습니다.");
                return;
            }

            string content = ReadChatContent(chatWindow, 250);
            if (string.IsNullOrWhiteSpace(content))
            {
                MessageBox.Show("대화 내용을 읽지 못했습니다.");
                return;
            }

            textBox3.Text = content;
        }


        private string ReadChatContent(IntPtr hwndKakaoTalk, int delay)
        {
            IntPtr listHwnd = FindChatListWindow(hwndKakaoTalk);
            if (listHwnd == IntPtr.Zero)
            {
                return null;
            }

            SetForegroundWindow(hwndKakaoTalk);
            Thread.Sleep(delay);

            FocusWindowByClick(listHwnd);
            Thread.Sleep(delay);

            string previousClipboard = null;
            TryGetClipboardText(out previousClipboard);

            string content = null;
            for (int attempt = 0; attempt < 5; attempt++)
            {
                SetForegroundWindow(hwndKakaoTalk);
                Thread.Sleep(delay);

                SafeClipboardClear();

                FocusWindowByClick(listHwnd);
                Thread.Sleep(delay + (attempt * 30));

                RECT rect;
                if (GetWindowRect(listHwnd, out rect))
                {
                    int width = rect.Right - rect.Left;
                    int height = rect.Bottom - rect.Top;
                    int clickX = rect.Left + Math.Min(width - 10, Math.Max(160, width / 3));
                    int clickY = rect.Top + Math.Min(height - 10, Math.Max(120, height / 3));

                    ClickAt(clickX, clickY);
                    Thread.Sleep(delay);
                    RightClickAt(clickX, clickY);
                    Thread.Sleep(delay + 150);
                    POINT p;
                    if (GetCursorPos(out p))
                    {
                        ClickContextMenuItem(p.X, p.Y, 10); // 전체 선택
                    }
                    else
                    {
                        SendKey(VK_A); // 전체 선택
                    }
                    Thread.Sleep(delay);

                    RightClickAt(clickX, clickY);
                    Thread.Sleep(delay);
                    if (GetCursorPos(out p))
                    {
                        ClickContextMenuItem(p.X, p.Y, 10); // 복사
                    }
                    else
                    {
                        SendKey(VK_C); // 복사
                    }
                    Thread.Sleep(delay + 250);
                }
                else
                {
                    SendCtrlKey(VK_A);
                    Thread.Sleep(delay + (attempt * 20));
                    SendCtrlKey(VK_C);
                    Thread.Sleep(delay + 80);
                }

                TryGetClipboardText(out content);
                if (!string.IsNullOrWhiteSpace(content))
                {
                    break;
                }
            }

            TrySetClipboardText(previousClipboard);

            return content ?? string.Empty;
        }