Skip to content

Commit ed0aceb

Browse files
authored
Create ScreenshotPRO_V2.py
1 parent 51d129a commit ed0aceb

1 file changed

Lines changed: 378 additions & 0 deletions

File tree

Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
1+
# ==========================================================
2+
# Screenshot PRO - Advanced Screen Capture Tool
3+
# Professional Desktop Tool
4+
# ==========================================================
5+
6+
import os
7+
import sys
8+
import threading
9+
import time
10+
import traceback
11+
from datetime import datetime
12+
from queue import Queue, Empty
13+
14+
import tkinter as tk
15+
from tkinter import filedialog, messagebox
16+
17+
import ttkbootstrap as tb
18+
from ttkbootstrap.constants import *
19+
20+
from PIL import ImageGrab, Image, ImageTk
21+
22+
import pygetwindow as gw
23+
24+
25+
# =================== APP CONFIG ===================
26+
27+
APP_NAME = "Screenshot PRO"
28+
APP_VERSION = "2.0.0"
29+
30+
31+
# =================== APP ===================
32+
33+
app = tk.Tk()
34+
app.title(f"{APP_NAME} {APP_VERSION}")
35+
app.geometry("1200x700")
36+
37+
tb.Style("darkly")
38+
39+
40+
# =================== UTILITY ===================
41+
42+
def resource_path(file_name):
43+
base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
44+
return os.path.join(base_path, file_name)
45+
46+
47+
def log_error():
48+
with open("error.log", "a", encoding="utf-8") as f:
49+
f.write(traceback.format_exc() + "\n")
50+
51+
52+
def show_about():
53+
messagebox.showinfo(
54+
f"About {APP_NAME}",
55+
f"{APP_NAME} v{APP_VERSION}\n\n"
56+
"Advanced Screen Capture Tool\n\n"
57+
"Features:\n"
58+
"• Full screen capture\n"
59+
"• Window capture\n"
60+
"• Smart region selector\n"
61+
"• Screenshot preview panel\n"
62+
"• Clipboard copy\n"
63+
"• Auto file naming\n"
64+
"• Processing log\n\n"
65+
"Built with Python + Tkinter + ttkbootstrap\n"
66+
)
67+
68+
69+
# =================== MENU ===================
70+
71+
menubar = tb.Menu(app)
72+
help_menu = tb.Menu(menubar, tearoff=0)
73+
help_menu.add_command(label="About", command=show_about)
74+
menubar.add_cascade(label="Help", menu=help_menu)
75+
app.config(menu=menubar)
76+
77+
78+
# =================== FLAGS ===================
79+
80+
ui_queue = Queue()
81+
82+
output_path = tb.StringVar(value=os.getcwd())
83+
file_prefix = tb.StringVar(value="screenshot")
84+
85+
last_image = None
86+
87+
88+
# =================== TITLE ===================
89+
90+
tb.Label(
91+
app,
92+
text=APP_NAME,
93+
font=("Segoe UI", 24, "bold")
94+
).pack(pady=(10, 2))
95+
96+
tb.Label(
97+
app,
98+
text="Professional Screen Capture Tool",
99+
font=("Segoe UI", 10, "italic"),
100+
foreground="#9ca3af"
101+
).pack(pady=(0, 10))
102+
103+
104+
# =================== FRAME: SETTINGS ===================
105+
106+
frame1 = tb.Labelframe(app, text="Capture Settings", padding=10)
107+
frame1.pack(fill="x", padx=10, pady=6)
108+
109+
tb.Label(frame1, text="File Prefix:").pack(side="left")
110+
tb.Entry(frame1, textvariable=file_prefix, width=20).pack(side="left", padx=6)
111+
112+
tb.Label(frame1, text="Output Folder:", width=13).pack(side="left", padx=(20,0))
113+
tb.Entry(frame1, textvariable=output_path, width=40).pack(side="left", padx=6)
114+
115+
116+
def browse_output():
117+
folder = filedialog.askdirectory()
118+
if folder:
119+
output_path.set(folder)
120+
121+
tb.Button(frame1, text="Browse", command=browse_output).pack(side="left", padx=4)
122+
123+
124+
# =================== AUTO FILE NAME ===================
125+
126+
def generate_filename():
127+
128+
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
129+
130+
return f"{file_prefix.get()}_{ts}.png"
131+
132+
133+
# =================== SAVE IMAGE ===================
134+
135+
def save_image(img):
136+
137+
global last_image
138+
139+
try:
140+
141+
filename = generate_filename()
142+
143+
path = os.path.join(output_path.get(), filename)
144+
145+
img.save(path)
146+
147+
last_image = img
148+
149+
ui_queue.put(("preview", img))
150+
151+
ui_queue.put(("log", f"✔ Saved: {filename}"))
152+
153+
except:
154+
log_error()
155+
ui_queue.put(("log", "❌ Save failed"))
156+
157+
158+
# =================== FULLSCREEN CAPTURE ===================
159+
160+
def capture_fullscreen():
161+
162+
try:
163+
164+
img = ImageGrab.grab()
165+
166+
save_image(img)
167+
168+
except:
169+
log_error()
170+
171+
ui_queue.put(("progress", 100))
172+
173+
174+
# =================== WINDOW CAPTURE ===================
175+
176+
def capture_window():
177+
178+
try:
179+
180+
win = gw.getActiveWindow()
181+
182+
if not win:
183+
ui_queue.put(("log","❌ No active window"))
184+
return
185+
186+
bbox = (win.left, win.top, win.right, win.bottom)
187+
188+
img = ImageGrab.grab(bbox)
189+
190+
save_image(img)
191+
192+
except:
193+
log_error()
194+
195+
ui_queue.put(("progress",100))
196+
197+
198+
# =================== REGION SELECTOR ===================
199+
200+
def capture_region():
201+
202+
selector = tk.Toplevel()
203+
selector.attributes("-fullscreen", True)
204+
selector.attributes("-alpha", 0.25)
205+
selector.configure(bg="black")
206+
207+
canvas = tk.Canvas(selector, cursor="cross")
208+
canvas.pack(fill="both", expand=True)
209+
210+
start_x = start_y = 0
211+
rect = None
212+
213+
def press(e):
214+
nonlocal start_x, start_y, rect
215+
start_x = e.x
216+
start_y = e.y
217+
rect = canvas.create_rectangle(start_x,start_y,start_x,start_y,outline="red",width=2)
218+
219+
def drag(e):
220+
canvas.coords(rect,start_x,start_y,e.x,e.y)
221+
222+
def release(e):
223+
224+
x1 = min(start_x,e.x)
225+
y1 = min(start_y,e.y)
226+
x2 = max(start_x,e.x)
227+
y2 = max(start_y,e.y)
228+
229+
selector.destroy()
230+
231+
try:
232+
233+
img = ImageGrab.grab(bbox=(x1,y1,x2,y2))
234+
235+
save_image(img)
236+
237+
except:
238+
log_error()
239+
240+
ui_queue.put(("progress",100))
241+
242+
canvas.bind("<ButtonPress-1>",press)
243+
canvas.bind("<B1-Motion>",drag)
244+
canvas.bind("<ButtonRelease-1>",release)
245+
246+
247+
# =================== CLIPBOARD COPY ===================
248+
249+
def copy_clipboard():
250+
251+
global last_image
252+
253+
if not last_image:
254+
messagebox.showerror("Error","No screenshot yet")
255+
return
256+
257+
try:
258+
259+
import win32clipboard
260+
from io import BytesIO
261+
262+
output = BytesIO()
263+
last_image.convert("RGB").save(output,"BMP")
264+
data = output.getvalue()[14:]
265+
output.close()
266+
267+
win32clipboard.OpenClipboard()
268+
win32clipboard.EmptyClipboard()
269+
win32clipboard.SetClipboardData(win32clipboard.CF_DIB,data)
270+
win32clipboard.CloseClipboard()
271+
272+
ui_queue.put(("log","📋 Copied to clipboard"))
273+
274+
except:
275+
ui_queue.put(("log","❌ Clipboard copy failed"))
276+
277+
278+
# =================== BUTTONS ===================
279+
280+
frame_buttons = tb.Frame(app)
281+
frame_buttons.pack(fill="x", padx=10, pady=6)
282+
283+
tb.Button(frame_buttons,text="📸 Full Screen",bootstyle="success",
284+
command=lambda: threading.Thread(target=capture_fullscreen,daemon=True).start()
285+
).pack(side="left",padx=4)
286+
287+
tb.Button(frame_buttons,text="🖥 Window Capture",bootstyle="info",
288+
command=lambda: threading.Thread(target=capture_window,daemon=True).start()
289+
).pack(side="left",padx=4)
290+
291+
tb.Button(frame_buttons,text="🎯 Region Capture",bootstyle="warning",
292+
command=capture_region
293+
).pack(side="left",padx=4)
294+
295+
tb.Button(frame_buttons,text="📋 Copy Clipboard",bootstyle="secondary",
296+
command=copy_clipboard
297+
).pack(side="left",padx=4)
298+
299+
300+
# =================== PROGRESS ===================
301+
302+
frame2 = tb.Labelframe(app, text="Progress", padding=8)
303+
frame2.pack(fill="x", padx=10)
304+
305+
progress_var = tb.IntVar()
306+
307+
tb.Progressbar(frame2,variable=progress_var,maximum=100,length=400).pack(side="left", padx=10)
308+
309+
status_lbl = tb.Label(frame2,text="Status: Ready")
310+
status_lbl.pack(side="left",padx=10)
311+
312+
313+
# =================== MAIN LAYOUT ===================
314+
315+
main_frame = tb.Frame(app)
316+
main_frame.pack(fill="both",expand=True,padx=10,pady=6)
317+
318+
# preview panel
319+
preview_frame = tb.Labelframe(main_frame,text="Preview",padding=8)
320+
preview_frame.pack(side="left",fill="both",expand=True,padx=6)
321+
322+
preview_label = tk.Label(preview_frame)
323+
preview_label.pack(expand=True)
324+
325+
# log panel
326+
log_frame = tb.Labelframe(main_frame,text="Processing Log",padding=8)
327+
log_frame.pack(side="right",fill="both",expand=True,padx=6)
328+
329+
log_text = tk.Text(log_frame,height=10)
330+
log_text.pack(side="left",fill="both",expand=True)
331+
332+
scroll = tk.Scrollbar(log_frame,command=log_text.yview)
333+
scroll.pack(side="right",fill="y")
334+
335+
log_text.config(yscrollcommand=scroll.set,state="disabled")
336+
337+
338+
# =================== UI QUEUE ===================
339+
340+
def process_ui_queue():
341+
342+
try:
343+
344+
while True:
345+
346+
cmd,data = ui_queue.get_nowait()
347+
348+
if cmd=="progress":
349+
progress_var.set(data)
350+
351+
elif cmd=="log":
352+
353+
log_text.config(state="normal")
354+
log_text.insert("end",data+"\n")
355+
log_text.see("end")
356+
log_text.config(state="disabled")
357+
358+
elif cmd=="preview":
359+
360+
img = data.copy()
361+
img.thumbnail((550,400))
362+
363+
tk_img = ImageTk.PhotoImage(img)
364+
365+
preview_label.config(image=tk_img)
366+
preview_label.image = tk_img
367+
368+
except Empty:
369+
pass
370+
371+
app.after(100,process_ui_queue)
372+
373+
374+
# =================== START UI ===================
375+
376+
app.after(100,process_ui_queue)
377+
378+
app.mainloop()

0 commit comments

Comments
 (0)