An để camera ở nhà, coi trên máy tính bằng Ezviz Studio, phần mềm chính hãng của
hãng camera EZVIZ. Coi thì được, mà xài lâu có ba thứ làm An quạu:

  1. Cửa sổ không kéo được. Rê chuột vô cạnh cửa sổ, con trỏ không thèm đổi
    thành mũi tên hai chiều. Muốn đổi kích thước phải nhắm trúng một vệt mỏng dính.

  2. Cứ vài phút cái Ezviz ngôn lù này lại chặn màn hình, hỏi có xem tiếp hông 😂
    Không bấm thì video đứng luôn.

  3. Muốn tắt tiếng riêng nó thì phải tắt loa cả máy, tại thanh âm lượng trong
    app thỉnh thoảng tự bật lên lại.

Mò ba tuần, An ra được cái tool nằm ở khay đồng hồ, làm giùm hết ba việc đó. Bài
này An kể lại đường đi, kể cả mấy khúc đi nhầm, tại phần đó mới là phần hiếm thấy
trong mấy bài kỹ thuật.

📥 Lấy tool về xài liền

Tải Ezviz Helper (file ZIP, 4,3 MB)

Giải nén ra chỗ nào cũng được, bấm đúp tools\CAI-DAT-LAN-DAU.cmd, hiện UAC thì
bấm Yes. Xong. Từ đó cứ mở Ezviz như thường, tool nằm sẵn ở khay đồng hồ.

Mã nguồn mở, giấy phép MIT, coi ở
GitHub. Không có file
nhị phân nào hết, toàn bộ là script mở bằng Notepad đọc được. Cần quyền Admin,
lý do An kể ở phần dưới.

Ai chỉ cần cái tool thì lấy tới đây là đủ. Phần còn lại là chuyện An mổ xẻ nó.

Ezviz Studio phiên bản 2.16.5, hộp thoại About
Bản An đang xài lúc viết bài là 2.16.5. Hình camera đã làm mờ.

Vì sao cửa sổ không kéo được

Việc đầu tiên là hỏi Windows coi cái cửa sổ đó được khai báo ra sao. Hàm
GetWindowLong trả về kiểu cửa sổ là 0x96020000. Dịch ra:

WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MINIMIZEBOX

Chuyện đáng nói nằm ở thứ KHÔNG có trong danh sách: không có WS_THICKFRAME
(cờ báo "cửa sổ này kéo giãn được"), cũng không có WS_CAPTION (thanh tiêu đề).
Ezviz vẽ thanh tiêu đề riêng bằng Qt cho đẹp, mà làm vậy thì bỏ luôn phần khung
của Windows.

Hệ quả: Windows không hề cấp cho cửa sổ này một cái viền kéo nào. Cái vệt
mỏng mà An vẫn ráng nhắm trúng là do Qt tự vẽ tự bắt, rộng chừng 3 pixel.
Không phải An gà đâu nha, nó đúng là chỉ có ba pixel thiệt.

Biết vậy rồi thì cách trị rõ liền: đừng đi kiếm cái viền không tồn tại, tự làm ra
một cái. Tool của An cài một cái móc chuột toàn hệ thống (WH_MOUSE_LL), rồi quy
ước:

  • Giữ ALT + kéo chuột phải = đổi kích thước, kéo ở bất kỳ đâu trong cửa sổ

  • Giữ ALT + kéo chuột trái = di chuyển cửa sổ

Kéo ở nửa trái thì co cạnh trái, kéo ở góc dưới-phải thì co đúng góc đó. Nghĩa là
nguyên cái cửa sổ trở thành viền kéo.

Tab Kéo nhanh của Ezviz Helper
Nguyên cửa sổ thành viền kéo. Chọn phím bổ trợ ALT hay CTRL+ALT tuỳ thói quen.

Một bài học mắc tiền về cái móc chuột

Móc WH_MOUSE_LL do luồng giao diện của chính chương trình bạn phục vụ. Trong
lúc chờ hàm móc trả lời, Windows giữ con trỏ chuột đứng im. Không phải chỉ
trong app của bạn, mà nguyên cả máy.

Bản đầu An làm hơi nhiều việc trong hàm móc đó. Kết quả: nguyên con chuột cả máy
giật đùng đùng mỗi lần bấm ALT 😅

Sửa bằng cách trong hàm móc chỉ ghi vài con số rồi trả lời liền, việc nặng đẩy qua
chỗ khác. Ai tính viết móc chuột thì nhớ giùm cái này nha, nó không nằm ở chỗ dễ
thấy trong tài liệu.

Bức tường quyền hạn

Đổi kích thước cửa sổ thì gọi SetWindowPos. An gọi, và nó trả về
err=5, truy cập bị từ chối.

Lý do là một cơ chế của Windows tên UIPI: **tiến trình quyền thấp không được gửi
lệnh cho cửa sổ của tiến trình quyền cao.** Ezviz Studio chạy quyền Admin, tool
của An chạy quyền thường, nên mọi lệnh gửi qua đều bị chặn ngay ở tầng hệ điều
hành. Không phải bug, mà là hàng rào cố ý.

Không có mẹo nào lách được cái này, mà cũng không nên có. Cách duy nhất là **tool
cũng phải chạy quyền Admin**. Đó là lý do bản của An tự đăng ký một tác vụ trong
Task Scheduler với quyền cao nhất, vừa để chạy cùng Windows, vừa để khỏi hiện bảng
UAC mỗi lần khởi động.

Đáng chú ý: phần tắt tiếng thì không cần Admin. Nó đi đường khác, kể ở dưới.

Video không giãn theo cửa sổ, và giả thuyết sai của An

Kéo được cửa sổ rồi thì lòi ra chuyện mới: khung cửa sổ to ra, mà **hình camera
bên trong vẫn giữ nguyên cỡ cũ**, chừa một vành đen quanh mép.

Giả thuyết đầu tiên của An: Ezviz bỏ qua thông báo đổi kích thước khi lệnh tới từ
chương trình khác, nên chỉ cần gửi thêm vài thông báo nữa cho nó biết. An gửi đủ
kiểu. Không cái nào ăn thua. Giả thuyết đó sai.

Thứ cuối cùng có tác dụng lại là một trình tự nhìn trớt quớt:

Phóng to hết cỡ  -> chờ 450ms
Thu về như cũ    -> chờ 250ms
Đặt lại kích thước mong muốn -> chờ 150ms

Chừng 850 mili giây và một cái nháy màn hình. Lý do chắc là Ezviz chỉ tính lại
bề mặt video khi chính Windows báo trạng thái cửa sổ thay đổi (phóng to, thu nhỏ),
chứ không tính lại khi kích thước đơn thuần thay đổi. Nháy một cái, đổi lấy hình
đầy khung, An thấy đáng.

An kể chỗ này tại nó dạy An một điều: khi một giả thuyết đẹp mà không chạy, đừng
ráng vá cho nó chạy. Quăng đi, rồi thử cái coi bộ khùng khùng.

Tab Kích thước của Ezviz Helper
Đặt cỡ lẹ, lưu cỡ ưng ý, và nút ép video khớp khung, chính là cái trình tự 850ms ở trên.

Hộp thoại Continue: bấm giùm, mà đừng đụng vô chuột

Đây là thứ phiền nhất. Đang coi thì Ezviz dựng một hộp thoại chắn ngay giữa màn
hình, hỏi có muốn coi tiếp không, kèm một nút xanh mời mua gói VIP ngay bên cạnh.

Hộp thoại Streaming media has been playing for a long time
Bản cũ: hộp thoại 364x140, nút Continue nằm bên trái nút VIP.

Việc cần làm là bấm giùm nút Continue. Mà có một ràng buộc: **không được đụng
vô con chuột thật.** An hay vừa coi camera vừa làm việc khác. Nếu tool nhảy vô
cướp con trỏ giữa chừng thì nó còn phiền hơn cái hộp thoại.

Cách làm là gửi thẳng ba tin nhắn WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_LBUTTONUP
vô cửa sổ hộp thoại, với toạ độ tính theo hộp thoại chứ không theo màn hình.
Cửa sổ nhận được đúng một cú bấm, con trỏ thật không nhúc nhích một pixel.

Chỗ khó: Qt không có nút riêng cho An bám vô

Với app Windows thường, mỗi cái nút là một cửa sổ con có tên tuổi đàng hoàng, kiếm
dễ. Qt thì không. Nguyên cái hộp thoại chỉ là một cửa sổ duy nhất, mấy cái nút
được vẽ lên bên trong như vẽ tranh. Thử hỏi qua cổng trợ năng của Windows cũng chỉ
nhận về đúng một khối vô danh.

Nên An đành đo bằng tay: chụp hộp thoại lại, đếm pixel kiếm khung nút, rồi ghi vị
trí nút theo tỉ lệ so với hộp thoại. Kiểu như "nút Continue nằm ở 42,1% chiều
ngang và 88% chiều dọc". Cách này thô, mà được cái hộp thoại hiện chỗ nào trên màn
hình cũng bấm trúng.

Rồi Ezviz cập nhật, và mọi thứ đờ mờ nó, đập đi xây lại 😂

Một bữa An lỡ tay bấm cập nhật lên bản 2.16.5. Tool im ru. Vẫn chạy, không báo
lỗi gì, chỉ là hết bấm giùm.

Ezviz đổi hẳn kịch bản. Giờ có hai hộp thoại nối nhau:

  • Hộp thứ nhất, cỡ 430x200, báo "You've viewed the video for 5 minutes", nút
    Continue có đồng hồ đếm ngược 5 giây.

  • Hết 5 giây mà không bấm, hộp đó biến mất, hộp thứ hai hiện ra và **luồng video
    đã ngừng**.

Hộp thoại đếm ngược Continue 3
Bản mới: nút ghi Continue 3, đang đếm ngược. Không bấm kịp trong 5 giây là mất luồng.

Nghĩa là hết được thong thả. Phải bấm vô hộp thứ nhất. Bấm vô hộp thứ hai thì
trễ mất rồi.

Chỗ này An phải quyết một chuyện thiết kế. Máy An lên bản mới, mà người khác đọc
bài này có thể còn xài bản cũ. Nên An không sửa số cũ thành số mới, mà chuyển qua
một danh sách hồ sơ hộp thoại. Mỗi hồ sơ ghi lớp cửa sổ, tiêu đề, kích thước,
sai số cho phép, vị trí nút theo tỉ lệ, và một mức ưu tiên:

{ "Name": "Continue5", "W": 430, "H": 200, "RX": 0.421, "RY": 0.88, "Uutien": 100 }
{ "Name": "Streaming", "W": 364, "H": 140, "RX": 0.503, "RY": 0.714, "Uutien": 10 }

Hồ sơ cũ giữ nguyên, hồ sơ mới thêm vô. Bản nào cũng chạy. Và khi hai hộp cùng
hiện, cái ưu tiên 100 được bấm trước, đúng cái đang đếm ngược.

An thêm một thứ nữa mà giờ nghĩ lại thấy đáng giá nhất: khi tool thấy một hộp thoại
lạ, đúng lớp cửa sổ của Ezviz, cỡ hợp lý, mà không khớp hồ sơ nào, thì nó **tự
chụp lại và ghi vô nhật ký**. Lần cập nhật sau, thay vì ngồi đoán, An chỉ việc mở
ảnh ra đo rồi thêm một dòng vô cấu hình.

Một cải tiến An tự quăng đi

Có lúc An tính cho tool nhận diện hộp thoại ở nhiều mức phóng màn hình, nhân
kích thước với 1,25 và 1,5 cho hợp với máy đặt phóng to chữ. Nghe hợp lý.

Rồi An lập bảng thử. Một hộp thoại lạ cỡ 382x312 sẽ khớp nhầm hồ sơ 260x200 ở
mức 1,25x, tại sai số cho phép của hồ sơ cũ rộng quá. Nghĩa là tool sẽ bấm mù vô
một hộp thoại nó không biết là hộp gì.

An quăng luôn tính năng đó. Không bấm còn hơn bấm nhầm. Một cú bấm mù có thể
rơi trúng nút "Mua VIP". Có những cải tiến mà việc đúng nhất là liệng nó đi.

Tắt tiếng đúng một app, không đụng loa cả máy

Windows có sẵn cơ chế cho việc này. Mỗi chương trình phát tiếng đều có một "phiên
âm thanh" riêng, tắt được từng phiên độc lập, đúng cái bảng trộn âm mà bạn thấy
khi bấm chuột phải vô cái loa ở khay đồng hồ. Việc của tool là duyệt mấy phiên đó,
kiếm phiên thuộc về Ezviz, rồi bật cờ tắt tiếng.

Phần này không cần quyền Admin, khác hẳn phần cửa sổ.

Ezviz thỉnh thoảng tự bật tiếng lại, nên tool kiểm tra đều rồi tắt đè trong khoảng
0,2 giây, lẹ tới mức chưa kịp nghe thấy gì.

Ở bản 2.16.5, phần này cũng hư. An viết một đoạn kiểm tra để liệt kê toàn bộ phiên
âm thanh trong máy, và thấy nguyên nhân: **EzvizStudio.exe không còn giữ phiên
âm thanh nào hết.** Tiếng giờ do một tiến trình con tên PlayCtrlProcess.exe phát
ra.

Cách trị: đừng kiếm theo đúng một tiến trình, mà dựng nguyên cây tiến trình, từ
Ezviz đi xuống con, cháu, rồi tắt tiếng mọi phiên thuộc về cây đó. Máy An ra 11
tiến trình. Cách này có cái hay là bản cũ vẫn đúng, tại cây tiến trình bao giờ
cũng chứa chính nó.

Tab Tự động của Ezviz Helper
Tự bấm Continue, tự áp kích thước đã lưu, tắt tiếng cố định, và dán nhãn ĐANG TẮT TIẾNG lên cửa sổ Ezviz.

Còn một chi tiết nhỏ mà An thấy quan trọng: khi đang tắt tiếng, tool **dán một nhãn
đỏ "ĐANG TẮT TIẾNG"** đè lên góc cửa sổ Ezviz. Tại tắt tiếng ngầm là kiểu tự gài
bẫy chính bạn. Ba bữa sau bạn sẽ ngồi thắc mắc sao camera không có tiếng, rồi đi
lục driver âm thanh. Trạng thái ẩn thì phải cho người ta thấy.

Bốn thứ hư mà không hề báo lỗi

Đây là phần An muốn viết nhất, tại nó tốn của An nhiều thời gian hơn mọi phần kỹ
thuật ở trên cộng lại. Cả bốn đều không ném ra một lỗi nào.

1. PowerShell đọc sai tiếng Việt. File script không có dấu nhận dạng mã hoá ở
đầu thì PowerShell 5.1 đọc theo bảng mã cũ, và mọi chữ có dấu thành ký tự rác.
Không lỗi, chỉ là giao diện tự nhiên loạn chữ.

2. Task Scheduler âm thầm nuốt mất chốt canh. An đăng ký tác vụ với hai mốc
chạy: một lúc đăng nhập, một lặp lại mỗi 10 phút để tự hồi sinh nếu bị tắt giữa
chừng. Windows nhận, báo thành công, rồi giữ lại đúng một mốc. Tài liệu hướng
dẫn của An khoe tính năng tự hồi sinh suốt mấy tháng trời trong khi nó không hề tồn
tại. Giờ tool đọc ngược lại tác vụ sau khi đăng ký để đếm coi đủ mốc không,
thiếu thì ghi cảnh báo.

3. Chuyển dữ liệu qua JSON bị cắt cụt. Hàm chuyển đổi của PowerShell mặc định
chỉ đi sâu 2 tầng, phần sâu hơn bị thay bằng một dòng chữ mô tả. Cấu hình hộp thoại
của An nằm ở tầng 3. Lưu xong, mở ra thì rỗng.

4. Cái này thì An tự hại An. An mở một cửa sổ theo dõi nhật ký kiểu bám
đuôi file. Trên Windows, việc đó khoá file lại. Tool ghi nhật ký không được, mà
hàm ghi nhật ký lại bọc trong khối bắt lỗi nên im ru bỏ qua. An nhìn file nhật
ký trống trơn rồi hai lần kết luận nhầm là tính năng tự bấm đã hư. Nó vẫn chạy
tốt từ đầu tới giờ. Tệ hơn: An tắt cửa sổ theo dõi mà tiến trình bám đuôi vẫn sống,
giữ khoá thêm 12 phút nữa.

Bài học rút ra, viết bự cho An của sau này: **một chương trình im ru không có nghĩa
là nó đang chạy tốt.** Và nếu bạn bọc hàm ghi nhật ký trong khối bắt lỗi để nó
"không bao giờ làm sập chương trình", thì bạn vừa đẻ ra một chỗ có thể hư mà không
ai hay.

Giờ nó là cái gì

Một file PowerShell chừng 1800 dòng, có nhúng vài đoạn C# để gọi thẳng vô
Windows, chạy thu gọn ở khay đồng hồ. Không cài đặt, không dịch ra file thực thi.
An cố ý giữ nguyên dạng script để ai cũng mở ra đọc và sửa được, và để trình diệt
virus khỏi nghi ngờ một file lạ đi rình cửa sổ người khác.

Nó làm bốn việc: cho kéo cửa sổ ở bất kỳ đâu, nhớ rồi áp lại cỡ cửa sổ ưng ý, bấm
giùm Continue, và tắt tiếng riêng Ezviz.

Mã nguồn An để mở hết, giấy phép MIT, ai xài sao cũng được:

Một lưu ý cho ai tải về: Windows hay chặn file lấy từ mạng. Chuột phải file ZIP
trước khi giải nén, vô Properties, thấy ô Unblock thì tick vô rồi bấm OK.
Không làm bước này thì PowerShell nó chặn, ngồi đoán hoài không ra.

Nếu bạn cũng đang quạu với Ezviz Studio thì cách nghĩ ở đây xài lại được cho gần
như mọi phần mềm cứng đầu khác trên Windows: **hỏi hệ điều hành coi cái cửa sổ đó
thiệt ra là gì**, chấp nhận mấy hàng rào không nên lách, đo bằng tay thứ không hỏi
được, rồi ghi lại tử tế mọi thứ chưa hiểu, để lần sau khỏi ngồi đoán.