10

I want to display an image in OpenCV in a full screen borderless window. In other words, only the image pixels will appear, without menu, toolbar, or window background.

Using imshow() or cvShowImage() don't enable it:

  1. The window grows to be full screen in width but not in height. It misses few pixels.
  2. I could not make it borderless even by changing settings of window handler.

I think that the problem is rooted in cvNamedWindow() method which creates main WS_OVERLAPPED window, then creates a child and all functions like imshow() or cvGetWindowHandle() operate on the child.

Thus even windows command:

SetWindowLong((HWND)cvGetWindowHandle(winName), GWL_STYLE, WS_VISIBLE | WS_EX_TOPMOST | WS_POPUP);

Doesnt help, since the child cannot become borderless WS_POPUP. Someone got a workaround?

  • Maybe, showing opencv mat to window without using opencv built in methods
  • Or some kind of windows trick

P.S. I tried the following code:

cvMoveWindow("AAA",0,0);
cvSetWindowProperty("AAA", CV_WINDOW_FULLSCREEN, CV_WINDOW_FULLSCREEN);

// Also I tried this:
HWND hwnd = (HWND)cvGetWindowHandle("AAA");
RECT windowRect;
windowRect.left = 0;
windowRect.top = 0;
windowRect.right = cxScreen; //Display resolution
windowRect.bottom = cyScreen; //Display resolution
AdjustWindowRect(&windowRect,WS_VISIBLE,false);
long p_OldWindowStyle = SetWindowLongPtr(hwnd,GWL_STYLE,WS_POPUP);
SetWindowPos(hwnd,HWND_TOP,0,0,windowRect.right,windowRect.bottom,SWP_FRAMECHANGED | SWP_SHOWWINDOW);
SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE | WS_EX_TOPMOST | WS_POPUP); 
karlphillip
  • 92,053
  • 36
  • 243
  • 426
DanielHsH
  • 4,287
  • 3
  • 30
  • 36

1 Answers1

16

Have you issued cvShowImage() to display the window? Because it seems you are not doing it. Anyway, you might want to call the win32 API for this instead, so add a call to ShowWindow(hwnd, SW_SHOW); after SetWindowPos().

If your current call to SetWindowPos() doesn't do the trick, check this answer: Hide border of window, if i know a handle of this window

I recommend you doing your tests without calling cvSetWindowProperty() at first, just to make sure you can find a method that works.

Just a note, if you check modules/highgui/src/window_w32.cpp you can see how OpenCV creates windows on Windows.

EDIT:

The following code implements the tips I gave before and bypasses the problems the OP reported. The trick is NOT using cvGetWindowHandle() to retrieve the windows' handle and use directly win32 API for that: FindWindow()

IplImage* cv_img = cvLoadImage("test.jpg", CV_LOAD_IMAGE_UNCHANGED);
if(!cv_img)
{
    printf("Failed cvLoadImage\n");
    return -1;
}

cvNamedWindow("main_win", CV_WINDOW_AUTOSIZE);
cvMoveWindow("main_win", 0, 0);
cvSetWindowProperty("main_win", CV_WINDOW_FULLSCREEN, CV_WINDOW_FULLSCREEN);

cvShowImage("main_win", cv_img);

//HWND cv_hwnd = (HWND)cvGetWindowHandle("main_win");
//if (!cv_hwnd)
//{
//  printf("Failed cvGetWindowHandle\n");
//}
//printf("cvGetWindowHandle returned %p\n", *cv_hwnd);

HWND win_handle = FindWindow(0, L"main_win");
if (!win_handle)
{
    printf("Failed FindWindow\n");
}

SetWindowLong(win_handle, GWL_STYLE, GetWindowLong(win_handle, GWL_EXSTYLE) | WS_EX_TOPMOST);
ShowWindow(win_handle, SW_SHOW);

cvWaitKey(0);

cvReleaseImage(&cv_img);
cvDestroyWindow("main_win");

This code will make the window created by OpenCV borderless, but you still might have to tweak one thing or another to make this operation perfect. You'll see why. One idea is to resize the window and make it the size of the image.

EDIT:

Well, since you stated:

writing a demo might be very hard

I also decided to do this last part for you, since I'm such a nice guy =]

This is a small improvement of the code above:

HWND win_handle = FindWindow(0, L"main_win");
if (!win_handle)
{
    printf("Failed FindWindow\n");
}

// Resize
unsigned int flags = (SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER);
flags &= ~SWP_NOSIZE;
unsigned int x = 0;
unsigned int y = 0;
unsigned int w = cv_img->width;
unsigned int h = cv_img->height;
SetWindowPos(win_handle, HWND_NOTOPMOST, x, y, w, h, flags);

// Borderless
SetWindowLong(win_handle, GWL_STYLE, GetWindowLong(win_handle, GWL_EXSTYLE) | WS_EX_TOPMOST);
ShowWindow(win_handle, SW_SHOW);

And on my system it displays exactly what you asked on the question.

Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • I'll try to write a demo for you and post here in 10 hours. – karlphillip Jun 29 '11 at 13:21
  • Now, whoever down voted my answer please explain why. These were super valid considerations and the OP might be missing something obvious. – karlphillip Jun 29 '11 at 13:23
  • Have you seen how I refrased my question. I found the source of the problem. So writing a demo might be very hard... – DanielHsH Jun 29 '11 at 13:49
  • Review my answer, test it, come back here and replace the *down vote* for an *up vote*, and then accept my question. Thank you very much, it was a pleasure. – karlphillip Jun 30 '11 at 03:19
  • 1
    Wow! Thanks. You really implemeted and optimized that for me. I think that you have just invested more love and help than I get from my friends :-). – DanielHsH Jun 30 '11 at 08:15
  • 1
    The nugget "Don't use cvGetWindowHandle and use WinAPI's FindWindow instead" just solved a similar issue I had where I could not get my OpenCV windows to stay always-on-top using WS_EX_TOPMOST. THANK YOU! – gkimsey Apr 11 '13 at 19:32
  • This method works with images less than monitor resolution. If I have an image with a resolution equal to my monitor, it left a grey bar at the bottom. How to remove that, please? – A.k. Jan 07 '19 at 10:29