Nếu bạn đã sử dụng LVM_GETITEMTEXTW nhưng vẫn không lấy được tên người dùng chứa ký tự tiếng Việt, có thể có một số vấn đề khác xảy ra. Bạn có thể kiểm tra lại các bước sau:
--
You received this message because you are subscribed to a topic in the Google Groups "Programmers" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/developerpaltalk/qmvNa8UeNAU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to developerpalta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/developerpaltalk/fbca008f-6f7e-45c2-8430-2f71f52c9ec6n%40googlegroups.com.
The Paltalk team's response indicates that to get member names and mic status:
However, the user's complaint suggests that previous attempts to get member names (likely using SysListView32) failed, possibly due to incorrect control identification, outdated window classes, or issues with Unicode handling. I’ll update the previous code to:
Below is the updated Python code that addresses the user’s request and incorporates the Paltalk team’s guidance.
Updated Python Code for Paltalk Room Member Names and Microphone Status
import win32gui
import win32con
import win32ui
import ctypes
import time
import pywinauto
from pywinauto import Application
import logging
import re
# Set up logging
logging.basicConfig(
filename=f"paltalk_log_{time.strftime('%Y-%m-%d')}.log",
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(message)s"
)
# Global variables
hwnd_chat = 0
hwnd_user_list = 0
room_list = []
def init_room_list():
"""Enumerate all open Paltalk chat room windows."""
def enum_windows_cb(hwnd, lparam):
class_name = win32gui.GetClassName(hwnd)
if class_name == "Qt5150QWindowIcon":
title = win32gui.GetWindowText(hwnd)
if title:
room_list.append(title)
return True
room_list.clear()
win32gui.EnumWindows(enum_windows_cb, 0)
if not room_list:
logging.warning("No chat rooms found.")
print("No chat rooms found.")
else:
logging.info(f"Found {len(room_list)} rooms: {', '.join(room_list)}")
print(f"Room list: {room_list}")
return room_list
def init_chat_hwnd(room_name):
"""Find the handles for the chat message and user list controls in the room."""
global hwnd_chat, hwnd_user_list
hwnd_chat = 0
hwnd_user_list = 0
def dlg_group_chat_cb(hwnd, lparam):
global hwnd_chat, hwnd_user_list
class_name = win32gui.GetClassName(hwnd)
if class_name in ["RichEdit20W", "RichEdit32", "RichEdit50W", "ui::controls::EmojiTextEdit"]:
hwnd_chat = hwnd
logging.debug(f"Found chat control: {class_name}, Handle: {hwnd}")
if class_name in ["SysListView32", "ui::controls::UserList"]:
hwnd_user_list = hwnd
logging.debug(f"Found user list control: {class_name}, Handle: {hwnd}")
return True
window = win32gui.FindWindow("Qt5150QWindowIcon", room_name)
if window == 0:
logging.error(f"Room window '{room_name}' not found.")
print(f"Room window '{room_name}' not found.")
return False
win32gui.EnumChildWindows(window, dlg_group_chat_cb, 0)
if hwnd_chat == 0:
logging.error(f"Chat message control not found in room '{room_name}'.")
print(f"Chat message control not found in room '{room_name}'.")
return False
if hwnd_user_list == 0:
logging.warning(f"User list control not found in room '{room_name}'. Trying UI Automation.")
print(f"User list control not found in room '{room_name}'.")
return True
def read_chat():
"""Read all messages from the chat display control."""
if hwnd_chat == 0:
logging.error("Chat control handle not initialized.")
print("Chat control handle not initialized.")
return []
try:
length = win32gui.SendMessage(hwnd_chat, win32con.WM_GETTEXTLENGTH, 0, 0)
if length <= 0:
logging.warning("No messages found in the room.")
print("No messages found in the room.")
return []
buffer = ctypes.create_unicode_buffer(length + 1)
win32gui.SendMessage(hwnd_chat, win32con.WM_GETTEXT, length + 1, buffer)
messages = buffer.value.split("\n")
messages = [msg.strip() for msg in messages if msg.strip()]
logging.info(f"Read {len(messages)} messages from the room.")
return messages
except Exception as e:
logging.error(f"Error reading messages: {str(e)}")
print(f"Error reading messages: {str(e)}")
return []
def read_system_messages(messages):
"""Filter system messages (join/leave/muted) from the message list."""
system_patterns = [
r".* has joined the room",
r".* has left the room",
r".* has been muted",
r".* has been unmuted"
]
system_messages = []
for msg in messages:
if any(re.match(pattern, msg, re.IGNORECASE) for pattern in system_patterns):
system_messages.append(msg)
logging.info(f"Found {len(system_messages)} system messages.")
return system_messages
def get_room_users():
"""Retrieve the list of current users and their mic status in the room from the SysListView32 control."""
if hwnd_user_list == 0:
logging.error("User list handle not initialized.")
print("User list handle not initialized.")
return []
try:
# Get the number of items in the ListView
item_count = win32gui.SendMessage(hwnd_user_list, win32con.LVM_GETITEMCOUNT, 0, 0)
if item_count <= 0:
logging.warning("No users found in the list.")
print("No users found in the list.")
return []
users = []
for i in range(item_count):
# Get nickname using LVM_GETITEMTEXTA
buffer = ctypes.create_string_buffer(256)
lvitem_text = (ctypes.c_uint * 5)(1, i, 0, 0, ctypes.addressof(buffer))
win32gui.SendMessage(hwnd_user_list, win32con.LVM_GETITEMTEXTA, i, lvitem_text)
nickname = buffer.value.decode('ascii', errors='ignore')
if not nickname:
continue
# Get mic status using LVM_GETITEMW
class LVITEMW(ctypes.Structure):
_fields_ = [
("mask", ctypes.c_uint),
("iItem", ctypes.c_int),
("iSubItem", ctypes.c_int),
("state", ctypes.c_uint),
("stateMask", ctypes.c_uint),
("pszText", ctypes.c_wchar_p),
("cchTextMax", ctypes.c_int),
("iImage", ctypes.c_int),
("lParam", ctypes.c_long),
("iIndent", ctypes.c_int)
]
lvitem_w = LVITEMW(mask=win32con.LVIF_IMAGE, iItem=i, iSubItem=0)
win32gui.SendMessage(hwnd_user_list, win32con.LVM_GETITEMW, 0, ctypes.byref(lvitem_w))
mic_on = lvitem_w.iImage == 10
# Get microphone queue flag using WM_USER + 1
is_asking_for_mic = win32gui.SendMessage(hwnd_user_list, win32con.WM_USER + 1, i, 0)
users.append({
"nickname": nickname,
"mic_on": mic_on,
"asking_for_mic": bool(is_asking_for_mic)
})
logging.info(f"Found {len(users)} users in the room.")
return users
except Exception as e:
logging.error(f"Error retrieving user list: {str(e)}")
print(f"Error retrieving user list: {str(e)}")
return []
def read_chat_pywinauto(room_name):
"""Read messages using pywinauto (fallback)."""
try:
app = Application().connect(title_re=".*" + room_name + ".*")
chat_window = app.window(title_re=".*" + room_name + ".*")
if not chat_window.exists():
logging.error(f"Room window '{room_name}' not found via pywinauto.")
print(f"Room window '{room_name}' not found via pywinauto.")
return []
# Find the chat message control
edit_control = None
for control in chat_window.descendants(control_type="Edit"):
class_name = control.class_name()
if class_name in ["RichEdit20W", "RichEdit32", "RichEdit50W", "ui::controls::EmojiTextEdit"]:
edit_control = control
break
if edit_control is None:
logging.error(f"Chat message control not found in room '{room_name}' via pywinauto.")
print(f"Chat message control not found in room '{room_name}'.")
return []
text = edit_control.get_value()
messages = text.split("\n")
messages = [msg.strip() for msg in messages if msg.strip()]
logging.info(f"Read {len(messages)} messages via pywinauto.")
return messages
except Exception as e:
logging.error(f"Error reading messages via pywinauto: {str(e)}")
print(f"Error reading messages via pywinauto: {str(e)}")
return []
def get_room_users_pywinauto(room_name):
"""Retrieve the user list using pywinauto (fallback)."""
try:
app = Application().connect(title_re=".*" + room_name + ".*")
chat_window = app.window(title_re=".*" + room_name + ".*")
if not chat_window.exists():
logging.error(f"Room window '{room_name}' not found via pywinauto.")
print(f"Room window '{room_name}' not found via pywinauto.")
return []
# Find the user list control
list_control = None
for control in chat_window.descendants(control_type="List"):
class_name = control.class_name()
if class_name in ["SysListView32", "ui::controls::UserList"]:
list_control = control
break
if list_control is None:
logging.error(f"User list control not found in room '{room_name}' via pywinauto.")
print(f"User list control not found in room '{room_name}'.")
return []
users = []
for item in list_control.items():
nickname = item.get_text()
if nickname:
# Note: pywinauto cannot retrieve mic status or queue flag; use Win32 for that
users.append({
"nickname": nickname,
"mic_on": False, # Placeholder; requires Win32 for accurate status
"asking_for_mic": False # Placeholder; requires Win32 for accurate status
})
logging.info(f"Found {len(users)} users via pywinauto.")
return users
except Exception as e:
logging.error(f"Error retrieving user list via pywinauto: {str(e)}")
print(f"Error retrieving user list via pywinauto: {str(e)}")
return []
if __name__ == '__main__':
# Enumerate rooms
init_room_list()
if not room_list:
print("Exiting because no rooms were found.")
exit(1)
room_name = room_list[0] # Select the first room, e.g., "Inner peace ♥"
print(f"Reading messages and user list from room: {room_name}")
# Initialize handles
if init_chat_hwnd(room_name):
# Read messages
messages = read_chat()
if messages:
print("Room Messages (Win32):")
for msg in messages:
print(f"- {msg}")
# Filter system messages
system_messages = read_system_messages(messages)
if system_messages:
print("\nSystem Messages (join/leave/muted):")
for msg in system_messages:
print(f"- {msg}")
else:
print("\nNo system messages found.")
else:
print("No messages retrieved via Win32.")
# Get user list with mic status
users = get_room_users()
if users:
print("\nUsers in Room (Win32):")
for user in users:
mic_status = "Mic On" if user["mic_on"] else "Mic Off"
queue_status = "Asking for Mic" if user["asking_for_mic"] else "Not Asking for Mic"
print(f"- {user['nickname']} ({mic_status}, {queue_status})")
else:
print("\nNo users retrieved via Win32.")
else:
print("Failed to initialize chat window via Win32.")
# Fallback with pywinauto
messages = read_chat_pywinauto(room_name)
if messages:
print("\nRoom Messages (pywinauto):")
for msg in messages:
print(f"- {msg}")
system_messages = read_system_messages(messages)
if system_messages:
print("\nSystem Messages (join/leave/muted, pywinauto):")
for msg in system_messages:
print(f"- {msg}")
else:
print("\nNo system messages found via pywinauto.")
else:
print("\nNo messages retrieved via pywinauto.")
users = get_room_users_pywinauto(room_name)
if users:
print("\nUsers in Room (pywinauto):")
for user in users:
print(f"- {user['nickname']} (Mic status unavailable via pywinauto)")
else:
print("\nNo users retrieved via pywinauto.")