How to embed GLFW window in to WinAPI window frame? - c++

I have the following working code, which attaches the OpenGL handle to an existing WinAPI window. It works fine and I can properly get the properties (height and width for example) of the WinAPI dialog through calling openGL glfwGetWindowSize(glfwWnd, &windowWidth, &windowHeight); function.
LPCTSTR WindowName = "Untitled - Notepad";
HWND hwnd = FindWindow("Notepad", WindowName);
if (!glfwInit()) {
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
GLFWwindow* glfwWnd = glfwAttachWin32Window(hwnd, window);
GLint windowWidth, windowHeight;
glfwGetWindowSize(glfwWnd, &windowWidth, &windowHeight);
But what I actually want is for window "My Title" to be embedded inside the Notepad window frame. Which is not happening as they are still two separate windows. Any way of achieving this?

Related

How do I create a centered GLFW window?

I'm looking for the SDL equivalent of
gWindow = SDL_CreateWindow( "SDL window",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
WINDOW_WIDTH, WINDOW_HEIGHT, windowFlags );
for GLFW. I can center the glfw window after its creation with the below code, however, for a split second, the window is shown non-centered. So it doesn't look smooth.
// init glfw
if (!initGLFW())
{
return -1;
}
// create main window
int count;
int windowWidth, windowHeight;
int monitorX, monitorY;
GLFWwindow* gWindow;
GLFWmonitor** monitors = glfwGetMonitors(&count);
const GLFWvidmode* videoMode = glfwGetVideoMode(monitors[0]);
// width: 75% of the screen
windowWidth = videoMode->width / 1.5;
// Aspect ratio 16 to 9
windowHeight = windowWidth / 16 * 9;
glfwGetMonitorPos(monitors[0], &monitorX, &monitorY);
gWindow = glfwCreateWindow(windowWidth, windowHeight, "Engine v" ENGINE_VERSION, NULL, NULL);
if (!gWindow)
{
glfwTerminate();
std::cout << "Failed to create main window" << std::endl;
return -1;
}
glfwSetWindowPos(gWindow,
monitorX + (videoMode->width - windowWidth) / 2,
monitorY + (videoMode->height - windowHeight) / 2);
From the documentation:
By default, newly created windows use the placement recommended by the window system. To create the window at a specific position, make it initially invisible using the GLFW_VISIBLE window hint, set its position and then show it.
Example
Using your code above, you would add a call to glfwWindowHint before glfwCreateWindow like so:
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
and once you have positioned the window where you would like it, make a call to glfwShowWindow like so:
glfwShowWindow(gWindow);
Depending on your use case, it may also be prudent to reset the window hints using glfwDefaultWindowHints after creating the window, to ensure that future window creation isn't modified.
Putting all that together, I have something like:
if (!glfwInit())
{
return -1;
}
int count;
int windowWidth, windowHeight;
int monitorX, monitorY;
GLFWwindow* gWindow;
GLFWmonitor** monitors = glfwGetMonitors(&count);
const GLFWvidmode* videoMode = glfwGetVideoMode(monitors[0]);
windowWidth = videoMode->width / 1.5;
windowHeight = windowWidth / 16 * 9;
glfwGetMonitorPos(monitors[0], &monitorX, &monitorY);
// (1). Set the visibility window hint to false for subsequent window creation
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
gWindow = glfwCreateWindow(windowWidth, windowHeight, "Engine v", NULL, NULL);
if (!gWindow)
{
glfwTerminate();
std::cout << "Failed to create main window" << std::endl;
return -1;
}
// (2). Reset the window hints to default
glfwDefaultWindowHints();
glfwSetWindowPos(gWindow,
monitorX + (videoMode->width - windowWidth) / 2,
monitorY + (videoMode->height - windowHeight) / 2);
// (3). Show the window
glfwShowWindow(gWindow);

How to center an opengl window with glfw?

I wanna draw an opengl window in center of the screen,however I searched everywhere but didn't find any answer to it. Below is a common snippet code of creating a window But it always show up in most left-top position.How can I control it.
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(400,200,"LearnOpenGl",NULL,NULL);
if(window == NULL)
{
cout<<"Failed to create GLFW window!!"<<endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
cout<<"Failed to initialize GLAD!!"<<endl;
return -1;
}
glViewport(400, 400, 100, 200);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while(!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
}
Please use this function "glfwSetWindowPos".
Here is an example.
#Himanshu answered a question on how to get the max-width and max-height of a window aka window size How to get maximum possible window size when creating window in MFC?
So with that piece of code, you can center it like below:
int width=800;// could declare them as "const int" if you like
int hight=800;
GLFWwindow* window = glfwCreateWindow(width,hight, "OpenGL", NULL, NULL);
int max_width = GetSystemMetrics(SM_CXSCREEN);
int max_hieght = GetSystemMetrics(SM_CYSCREEN);
glfwSetWindowMonitor(window, NULL, (max_width/2)-(width/2), (max_hieght/2) - (height/2), width, height, GLFW_DONT_CARE);
Here is a sample from my game engine made using glad and glfw it uses the windows api to find to screen resolution and then centers the window accordingly.
#include <iostream>
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <GLFW/glfw3.h>
#include <Windows.h>
const unsigned int width = 1600;
const unsigned int height = 900;
const char* title = "Frog2D";
void getDesktopResolution(int& horizontal, int& vertical)
{
RECT desktop;
const HWND hDesktop = GetDesktopWindow();
GetWindowRect(hDesktop, &desktop);
horizontal = desktop.right;
vertical = desktop.bottom;
}
int main()
{
glfwInit();
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); //borderless
int horizontal = 0;
int vertical = 0;
getDesktopResolution(horizontal, vertical);
GLFWwindow* window = glfwCreateWindow(width, height, title, NULL, NULL);
glfwSetWindowPos(window, horizontal / 2 - width / 2, vertical / 2 - height / 2);
return 0;
}

X11 Window/GLXWindow attributes to GLFWwindow

Im created GLX window, that contains CWOverrideRedirect attribute, and destroyed input shape, so it looks like OpenGL overlay. Now I am wanted to draw a 2d text or use ImGUI. A lot of examples use GLFW library. So, the main problem is to make GLFWwindow transparency and without input shape.
int attr_mask =
CWOverrideRedirect| //borderless, always on top
CWColormap|
CWBorderPixel|
CWEventMask;
window_handle = XCreateWindow( Xdisplay,
Xroot,
x, y, width, height,
0,
visual->depth,
InputOutput,
visual->visual,
attr_mask, &attr);
..............
// Destroy input shape
XRectangle rect;
XserverRegion region = XFixesCreateRegion(Xdisplay, &rect, 1);
XFixesSetWindowShapeRegion(Xdisplay, window_handle, ShapeInput, 0, 0, region);
XFixesDestroyRegion(Xdisplay, region);
if ((del_atom = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", 0)) != None) {
XSetWMProtocols(Xdisplay, window_handle, &del_atom, 1);
}
From ImGUI opengl3 example
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL3 example", NULL, NULL);
glfwMakeContextCurrent(window);
gl3wInit();

Change background of SDL2 window?

I can create a SDL2 window but I don't know how to change background color of this window.
My code:
#include "SDL.h"
SDL_Window *window;
void main()
{
window = SDL_CreateWindow("TEST", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
SDL_Delay(3000);
}
How can I change background color of this window to black?
You should set drawing colour with SDL_SetRenderDrawColor and then use SDL_RenderClear:
(code comes directly from SDL wiki)
int main(int argc, char* argv[])
{
SDL_Window* window;
SDL_Renderer* renderer;
// Initialize SDL.
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return 1;
// Create the window where we will draw.
window = SDL_CreateWindow("SDL_RenderClear",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
512, 512,
0);
// We must call SDL_CreateRenderer in order for draw calls to affect this window.
renderer = SDL_CreateRenderer(window, -1, 0);
// Select the color for drawing. It is set to red here.
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
// Clear the entire screen to our selected color.
SDL_RenderClear(renderer);
// Up until now everything was drawn behind the scenes.
// This will show the new, red contents of the window.
SDL_RenderPresent(renderer);
// Give us time to see the window.
SDL_Delay(5000);
// Always be sure to clean up
SDL_Quit();
return 0;
}
If you do not use SDL2 renderer you can do this:
Just call:
SDL_GL_SwapWindow(window);
After :
SDL_GL_MakeCurrent(window, context);
That's all! Now you have a black screen.
#include <SDL2/SDL.h>
#include <iostream>
using namespace std;
int main(){
int width=512, height=512;
SDL_Window *window=SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE);
if(window==NULL)
cout << "There was an error while initializing the window" << endl << SDL_GetError << endl;
SDL_Event event;
bool running=true;
while(running){
while(SDL_PollEvent(&event)){
if(event.type==SDL_QUIT){
running=false;
break;
}
}
SDL_GetWindowSize(window, &width, &height);
SDL_Surface *surface=SDL_GetWindowSurface(window);
Uint32 skyblue=SDL_MapRGB(surface->format, 65,193,193);
SDL_FillRect(surface, NULL, skyblue);
SDL_UpdateWindowSurface(window);
}
SDL_DestroyWindow(window);
SDL_Quit();
}
Note, none of these solutions work properly with OpenGL. The question was how to init the window with predefined color, not how to paint the first frame. There's still a blink of white color before the first frame is painted.
Try this one :
SDL_Window *wind;
SDL_Surface *windSurface = NULL
void main()
{
wind = SDL_CreateWindow("TEST", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
windSurface = SDL_GetWindowSurface(wind);
SDL_FillRect(windSurface, NULL, SDL_MapRGB(windSurface->format, 240, 200, 112));
SDL_UpdateWindowSurface(wind);
SDL_Delay(3000);
}

Resize SDL2 window?

Just made the jump from SDL1.2 to SDL2, been converting my code but couldn't figure out how to resize the window. Here's the code I have now:
SDL_DestroyWindow(Window);
Window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, ScreenSizeX, ScreenSizeY, SDL_WINDOW_SHOWN);
screen = SDL_GetWindowSurface(Window);
Which as you can see just destroys the window and creates a new one. Sloppy but it works. What I want is to just resize the window, is it possible?
I believe that that you could use the SDL_WINDOW_RESIZABLE flag in SDL_CreateWindow to make the window resizable.
You may look at the wiki doc: SDL_SetWindowSize
To resize a window in SDL, first set it with the flag SDL_WINDOW_RESIZABLE, then detect the resizing window event in a switch and finally call the following methods SDL_SetWindowSize(m_window, windowWidth, windowHeight) and glViewport(0, 0, windowWidth, windowHeight).
In the switch, use the flag SDL_WINDOWEVENT_RESIZED if you want only the final size of the window or SDL_WINDOWEVENT_SIZE_CHANGED if you want all the sizes between the first and the final.
To finish, update your own camera with the new window width and height.
m_window = SDL_CreateWindow("INCEPTION",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
m_windowWidth, m_windowHeight,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
switch (m_event.type) {
case SDL_WINDOWEVENT:
if (m_event.window.event == SDL_WINDOWEVENT_RESIZED) {
logFileStderr("MESSAGE:Resizing window...\n");
resizeWindow(m_event.window.data1, m_event.window.data2);
}
break;
default:
break;
}
void InceptionServices::resizeWindow(int windowWidth, int windowHeight) {
logFileStderr("MESSAGE: Window width, height ... %d, %d\n", windowWidth, windowHeight);
m_camera->resizeWindow(windowWidth, windowHeight);
glViewport(0, 0, windowWidth, windowHeight);
}
Window = SDL_CreateWindow(
"Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
ScreenSizeX,
ScreenSizeY,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
);
Use this function call