如何在Windows Forms中适配不同窗口尺寸的截图裁剪矩形
Great question! The core issue here is that your target cropping area scales proportionally with the game window's dimensions. Instead of manually estimating values for each resolution, we can compute the exact scaled rectangle using your original 640x480 baseline as a reference.
Step-by-Step Approach
1. Define Your Baseline Reference
First, store your original window size and corresponding cropping rectangle as constant reference values—this is your "source of truth" for all scaling calculations:
// Baseline: 640x480 window with confirmed cropping rectangle private readonly Size _originalWindowSize = new Size(640, 480); private readonly Rectangle _originalCropRect = new Rectangle(436, 150, 146, 170);
2. Calculate Scaling Factors
For any current window size, compute horizontal (scaleX) and vertical (scaleY) scaling factors by dividing the current dimensions by the baseline dimensions:
float scaleX = (float)currentWindowSize.Width / _originalWindowSize.Width; float scaleY = (float)currentWindowSize.Height / _originalWindowSize.Height;
Note: If your game maintains its original aspect ratio (like your 640x480 → 800x600 example), scaleX and scaleY will be identical. If the window is stretched non-proportionally, use the minimum of the two factors to avoid distorting the cropped target area.
3. Compute the Scaled Cropping Rectangle
Multiply each parameter of the original rectangle by the corresponding scaling factor, then round to the nearest integer (since Rectangle uses pixel-perfect integer coordinates):
int scaledX = (int)Math.Round(_originalCropRect.X * scaleX); int scaledY = (int)Math.Round(_originalCropRect.Y * scaleY); int scaledWidth = (int)Math.Round(_originalCropRect.Width * scaleX); int scaledHeight = (int)Math.Round(_originalCropRect.Height * scaleY); Rectangle scaledCropRect = new Rectangle(scaledX, scaledY, scaledWidth, scaledHeight);
4. Reusable Method Example
Wrap this logic in a clean, reusable method for easy integration into your Windows Forms code:
private Rectangle GetScaledCropRect(Size currentWindowSize) { // Baseline reference values Size originalSize = new Size(640, 480); Rectangle originalRect = new Rectangle(436, 150, 146, 170); // Calculate proportional scaling factors float scaleX = (float)currentWindowSize.Width / originalSize.Width; float scaleY = (float)currentWindowSize.Height / originalSize.Height; // Compute scaled rectangle parameters (rounded to pixel boundaries) int x = (int)Math.Round(originalRect.X * scaleX); int y = (int)Math.Round(originalRect.Y * scaleY); int width = (int)Math.Round(originalRect.Width * scaleX); int height = (int)Math.Round(originalRect.Height * scaleY); return new Rectangle(x, y, width, height); }
Verification with Your Examples
Let’s cross-check this with your manual estimates to show accuracy:
- For 800x600:
scaleX = 800/640 = 1.25,scaleY = 600/480 = 1.25- Scaled rect:
(545, 188, 183, 213)→ very close to your manual(546, 186, 186, 212)(the small gaps come from manual estimation error)
- For 1280x768:
- This resolution isn't a 4:3 aspect ratio like your baseline. If the game maintains its original ratio, it will likely render in a letterboxed area inside the window. In this case, calculate the scaled rectangle based on the actual game render size (not the full window size) to avoid cropping empty letterbox space.
Edge Case Handling
- Non-proportional resizing: If the game allows stretching to non-original ratios, choose to scale with width, height, or use the minimum scale factor to keep the target area intact.
- Pixel alignment: Using
Math.Round()ensures your cropped rectangle aligns perfectly with pixel boundaries, which is critical for clean bitmap cropping.
内容的提问来源于stack exchange,提问作者ElektroStudios

