C++ Wrong margin of the rackets in a window - c++

int width = 800;
int height = 600;
int interval = 1000 / 60;
int score_player1 = 0;
int score_player2 = 0;
int racket_width = 10;
int racket_height = 80;
int racket_speed = 8;
int racket_left_x = 10;
int racket_left_y = 50;
int racket_right_x = width - racket_width - 10;
int racket_right_y = 50;
Full code (without the class for the ball): http://pastebin.com/TA9NkV5c
The margin from the right racket to right side of the window is smaller than the left side. The variables for those are right calculated, but still, it is not equally.
http://i.imgur.com/2PA0pGz.png Link to the image

You've set the window to a width of 800 pixels, but everything else is positioned relative to the client region, which is narrower than the window width by the thickness of the border.
Use AdjustWindowRect to compute the size you have to make the window in order get the client area to be the desired size.
// Initialize a RECT with the size you want the client area to be.
RECT rc = { 0, 0, width, height };
// Now adjust the rectangle to the size the window would need to be.
AdjustWindowRect(&rc, my_style_flags, FALSE);
// Now create the window using the sizes in rc. Make sure you use
// consistent style flags or the adjustment may not be correct.
const int window_width = rc.right - rc.left;
const int window_height = rc.bottom - rc.top;
my_hwnd = CreateWindow(..., my_style_flags, x, y, window_width, window_height, ...);

Related

Windows: Window position X coordinate not accurate

I want to get the (accurate) on-screen X and Y coordinates of a window (the client area). My problem is that I have to define a horizontal shift which has to be added onto the X coordinate to get the correct result:
#include <windows.h>
inline int get_title_bar_thickness(const HWND window_handle)
{
RECT window_rectangle, client_rectangle;
GetWindowRect(window_handle, &window_rectangle);
GetClientRect(window_handle, &client_rectangle);
const int height = window_rectangle.bottom - window_rectangle.top -
(client_rectangle.bottom - client_rectangle.top);
const int width = window_rectangle.right - window_rectangle.left -
(client_rectangle.right - client_rectangle.left);
return height - width / 2;
}
#define HORIZONTAL_SHIFT 8
/**
* Gets the window position of the window handle
* excluding the title bar and populates the x and y coordinates
*/
inline void get_window_position(const HWND window_handle, int* x, int* y)
{
RECT rectangle;
const auto window_rectangle = GetWindowRect(window_handle, &rectangle);
const auto title_bar_thickness = get_title_bar_thickness(window_handle);
if (window_rectangle)
{
*x = rectangle.left + HORIZONTAL_SHIFT;
*y = rectangle.top + title_bar_thickness;
}
}
The issue can be observed by moving the window programmatically:
const auto window_handle = FindWindow(nullptr, "Command Prompt");
SetWindowPos(window_handle, nullptr, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
I would expect this SetWindowPos() call to perfectly place the window into the upper left corner of my screen but there is some space left between the window and the screen border (exactly 8 pixels). Is there a way to assure that this horizontal offset is automatically considered? This might be related to laptops so how to make this behave as expected?
As commented by Castorix, the horizontal shift can be retrieved.
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
inline int get_horizontal_shift(const HWND window_handle)
{
RECT window_rectangle, frame_rectangle;
GetWindowRect(window_handle, &window_rectangle);
DwmGetWindowAttribute(window_handle,
DWMWA_EXTENDED_FRAME_BOUNDS, &frame_rectangle, sizeof(RECT));
return frame_rectangle.left - window_rectangle.left;
}
The code is based on this post. The return value is 7 on my machine.

Calling ofSetWindowShape() in windowResized() freezes app on Ubuntu

I'm trying to make the OF window get resized proportionally maintaining the same ratio between width and height of the window.
For example, if you created a window with 400x300 dimensions and if you stretch the width to 800, then the height will automatically be stretched to 600 even though you only stretched the window horizontally.
Anyways, in order to implement this feature, I needed to use ofSetWindowShape() inside windowResized() listener.
I could quickly prototype this on MacOS X and it worked very well.
Here's the code:
ofApp.h
enum ScaleDir { //window scaling directions
SCALE_DIR_HORIZONTAL,
SCALE_DIR_VERTICAL,
};
ScaleDir scaleDir;
int windowWidth, windowHeight; //original window dimensions
float widthScaled, heightScaled; //scaled window dimensions
float windowScale; //scale amount (1.0 = original)
bool bScaleDirFixed; //is direction fixed?
ofApp.cpp
//--------------------------------------------------------------
void ofApp::setup(){
windowWidth = ofGetWidth();
windowHeight = ofGetHeight();
windowScale = 1.0f;
widthScaled = windowWidth * windowScale;
heightScaled = windowHeight * windowScale;
}
//--------------------------------------------------------------
void ofApp::update(){
if (bScaleDirFixed) {
bScaleDirFixed = false;
}
}
//--------------------------------------------------------------
void ofApp::draw(){
ofSetColor(255, 0, 0);
ofSetCircleResolution(50);
ofDrawEllipse(widthScaled/2, heightScaled/2, widthScaled, heightScaled); //the ellipse will be scaled as the window gets resized.
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
if (!bScaleDirFixed) {
int gapW = abs(widthScaled - w);
int gapH = abs(heightScaled - h);
if (gapW > gapH)
scaleDir = SCALE_DIR_HORIZONTAL;
else
scaleDir = SCALE_DIR_VERTICAL;
bScaleDirFixed = true;
}
float ratio;
if (scaleDir == SCALE_DIR_HORIZONTAL) {
ratio = static_cast<float>(windowHeight) / static_cast<float>(windowWidth);
h = w * ratio;
windowScale = static_cast<float>(w) / static_cast<float>(windowWidth);
}
else if (scaleDir == SCALE_DIR_VERTICAL) {
ratio = static_cast<float>(windowWidth) / static_cast<float>(windowHeight);
w = h * ratio;
windowScale = static_cast<float>(h) / static_cast<float>(windowHeight);
}
widthScaled = windowWidth * windowScale;
heightScaled = windowHeight * windowScale;
ofSetWindowShape(widthScaled, heightScaled);
}
However, if I run the same code on Ubuntu, the app freezes as soon as I resize the window. It seems ofSetWindowShape() calls windowResized() listener and therefore it goes into an infinite loop.
(windowResized -> ofSetWindowShape -> windowResized ->
ofSetWindowShape....)
How can I change the code so it can also work on Ubuntu without the problem?
Any advice or guidance would be greatly appreciated!
P.S: I would also appreciate if Linux users can confirm the app freezing.
Did you try:
ofSetupOpenGL(widthScaled, heightScaled, OF_WINDOW);
Apparently ofSetWindowShape() should only be called during App::Setup() ...
see OF tutorials here

How do I scale a rectangle to another rectangle (such as a picture to a window) preserving aspect ratio with the option to fill?

I'm putting this here because the algorithm for doing this is more difficult to find than it should be. Hopefully Google will cache this.
The problem is: you have a bitmap and a window. You want to draw the bitmap inside a window, filling the window, keeping the aspect ratio, as the window resizes.
You may also want to be able to fit it the other way, so that you can draw the image "over" the window, and all the area in the window will be filled. This will clip out some of the image. I present in the answer a simple algorithm for doing so.
Here's an implementation that uses integer math only.
The algorithm first stretches both dimensions, preserving aspect ratio. The new size is calculated, assuming that the respective other dimension occupies the entire space. Of these new dimensions, the one that overshoots the available area is set to the maximum possible value, while the other is scaled back, preserving aspect ratio. (For pan and scan (bScale is set to true) mode, the dimension that doesn't overshoot the available space is set to occupy the entire range.)
(Note: If sizePicture is an empty rectangle, this function returns a rectangle that stretches one pixel to the left and one pixel up, either from the origin, or the center.)
RECT size_rect( RECT& rcScreen,
RECT& sizePicture,
bool bCenter/*,
bool bScale*/ ) {
int clientWidth = rcScreen.right - rcScreen.left;
int clientHeight = rcScreen.bottom - rcScreen.top;
int picWidth = sizePicture.right - sizePicture.left;
int picHeight = sizePicture.bottom - sizePicture.top;
// Calculate new content size
int contentWidth = ::MulDiv( clientHeight, picWidth, picHeight );
int contentHeight = ::MulDiv( clientWidth, picHeight, picWidth );
// Adjust dimensions to fit inside client area
if ( contentWidth > clientWidth ) {
// To use the bScale parameter that allows the image to fill the entire
// client area, use the following if-clause instead.
//if ( ( bScale && ( contentWidth < clientWidth ) )
// || ( !bScale && ( contentWidth > clientWidth ) ) ) {
contentWidth = clientWidth;
contentHeight = ::MulDiv( contentWidth, picHeight, picWidth );
} else {
contentHeight = clientHeight;
contentWidth = ::MulDiv( contentHeight, picWidth, picHeight );
}
RECT rect = { 0 };
::SetRect( &rect, 0, 0, contentWidth, contentHeight );
if ( bCenter ) {
// Calculate offsets to center content
int offsetX = ( clientWidth - contentWidth ) / 2;
int offsetY = ( clientHeight - contentHeight ) / 2;
::OffsetRect( &rect, offsetX, offsetY );
}
return rect;
}
Make two RECT. One is the window you wish to fit to (passed into rcScreen), and the other holds the dimensions of the picture:
(pseudo-code)
RECT window;
GetClientRect(hwnd,&window)
RECT bitmap_rect;
BITMAP bitmap;
bitmap_rect.left = bitmap_rect.top = 0;
bitmap_rect.right = bitmap.bmWidth;
bitmap_rect.bottom = bitmap.bmHeight;
RECT draw_rect = size_rect(window,bitmap_rect,true,true);
Then StretchBlt it:
StretchBlt(toDC, draw_rect.left, draw_rect.top, draw_rect.right, draw_rect.bottom, fromDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
This is the function: (note there is no case for bCenter = false and Scale = true). **bCenter is flag for "center picture in window." Scale is flag for "pan and scan mode" instead of "letterbox," useful if you are using an image as a window background that you want resized but don't want to have letterboxes. **
RECT size_rect(RECT& rcScreen,
RECT& sizePicture,
bool bCenter,
bool Scale)
{
RECT rect = rcScreen;
double dWidth = rcScreen.right - rcScreen.left;
double dHeight = rcScreen.bottom - rcScreen.top;
double dAspectRatio = dWidth / dHeight;
double dPictureWidth = sizePicture.right - sizePicture.left;
double dPictureHeight = sizePicture.bottom - sizePicture.top;
double dPictureAspectRatio = dPictureWidth / dPictureHeight;
double nNewHeight = dHeight;
double nNewWidth = dWidth;
double nHeightCenteringFactor = 0;
double nWidthCenteringFactor = 0;
double xstart = rcScreen.left;
double ystart = rcScreen.top;
if (dPictureAspectRatio > dAspectRatio)
{
if (bCenter && Scale) {
nNewWidth = dPictureWidth*(1 / (dPictureHeight / dHeight));
xstart = rcScreen.left - ((nNewWidth / 2) - (dWidth / 2));
}
else {
nNewHeight = (int)(dWidth / dPictureWidth*dPictureHeight);
if (bCenter)
ystart = ((dHeight - nNewHeight) / 2) + rcScreen.top;
}
}
else if (dPictureAspectRatio < dAspectRatio)
{
if (bCenter && Scale) {
nNewHeight = dPictureHeight*(1 / (dPictureWidth / dWidth));
ystart = rcScreen.top - ((nNewHeight / 2) - (dHeight / 2));
}
else{
nNewWidth = (dHeight / dPictureHeight*dPictureWidth);
if (bCenter)
xstart = ((dWidth - nNewWidth) / 2) + rcScreen.left;
}
}
SetRect(&rect, xstart, ystart, nNewWidth, nNewHeight);
return rect;
}

c++ Xlib don't want to resize my window in height

I want to resize a window with Xlib so I made a function (she is inside a class) :
int setSizeAndMove(int top, int left, int width, int height)
{
XMoveResizeWindow(m_display, m_window_terminal, top, left, width, height);
return 1;
}
This function works fine. I have another function who return the size of the current window :
Rect getWindowSize() const
{
XWindowAttributes size_win;
XGetWindowAttributes(m_display, m_window_terminal, &size_win);
Rect size_return;
size_return.X = size_win.width;
size_return.Y = size_win.height;
return size_return;
}
(Rect is just a structur that contain int X & int Y)
My problem is when I do something like this :
setSizeAndMove(0, 0, getWindowSize().X + 10, getWindowSize().Y + 10);
The window correctly add 10 pixel to width but not to height, why ?
//Additional question with 0,0 the window isn't in the top left but something like 5,5.
Thanks for help.

Better control of my client area(WIN32)

I am trying to make a 3 x 3 grid with a black pen on a window. however I want it to be centered, for example that my grid is inside a white space,
10% of top, right, left and bottom. and my grid will fit in the remaining 80% even when we resize the window.
Now I could make the grid but after several attempts to create the 10% area, got frustrated.
case WM_SIZE:
//get the 10% range.
cxInvalid = LOWORD(lParam) * 0.1;
cyInvalid = HIWORD(lParam) * 0.1;
//get the grid, DIVISIONS = 3
cxBlock = LOWORD(lParam) / DIVISIONS;
cyBlock = HIWORD(lParam) / DIVISIONS;
return 0;
Thanks in advaced :)
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
for (x = 0; x < DIVISIONS; x++)
for (y = 0; y < DIVISIONS; y++)
{
Rectangle(hdc, x * cxBlock, y * cyBlock,
(x + 1) * cxBlock, (y + 1) * cyBlock);
}
EndPaint(hwnd, &ps);
return 0;
This is exactly the sort of problem for which Windows mapping modes are intended to be used. For the moment I'm going to assume that you want your grid to remain square, regardless of the shape of the window it's in.
One way to do that is to switch from the default MM_TEXT mapping mode to the MM_ISOTROPIC mapping mode (but if we want the grid to change shape with the surrounding window, we'd use MM_ANISOTRCOPIC instead).
Using that, we can set our window as a virtual grid of, say, 1200 x 1200 cells, and then draw our 3x3 grid on that. I've chosen 1200 x 1200 so the part we care about will be a nice, convenient 1000 x 1000 grid.
// set up the mapping mode:
RECT rect;
GetClientRect(hWnd, &rect);
SetMapMode(hDC, MM_ISOTROPIC);
SetViewportExt(rect.x, rect.y);
// The virtual width/height for our window:
static const int width = 1200;
static const int height = 1200;
SetWindowExt(width, height);
SetWindowOrg(-100, -100); // Set the virtual 0 point ~10% of the way into the window.
// And then draw the grid. We always draw in a 1000 x 1000 grid, and Windows
// scales that to the actual window size for us.
//
static const int grid_size = 1000;
static const int step = grid_size / 3;
for (int i = step; i < grid_size-1; i += step) {
MoveTo(hDC, i, 0);
LineTo(hDC, i, grid_size);
MoveTo(hDC, 0, i);
LineTo(hDC, grid_size, i);
}
To reiterate the difference between MM_ISOTROPIC and MM_ANISOTROPIC, here are screen shots of the grid. First as it's drawn with MM_ISOTROPIC:
...and then as it's drawn with MM_ANISOTROPIC: