How to resolve linking error for GetSystemMetrics()?

3.9k views Asked by At

I'm attempting to use the following to get the height & width of the main display:

#include <winuser.h>
size_t width = (size_t)GetSystemMetrics(SM_CXBORDER);
size_t height = (size_t)GetSystemMetrics(SM_CYBORDER);

However, it's failing on an unresolved externals link error (LNK1120). I've tried linking to user32.lib (as documented here), and received the same error, as well as linking to wmbase.lib (as documented here), and received the error that wmbase.lib does not exist! What am I doing wrong?

Note that I am only using plain-ol' C — not C++. Is this the right function to use to get the screen resolution (in pixels) of the main display?

I am attempting to compile this on MSVC at the moment, but would prefer a solution portable to other compilers.

Thanks.

Edit

So it looks like the parameters I was looking for were SM_CXSCREEN and SM_CYSCREEN, not SM_CXBORDER and SM_CYBORDER. However, I still can't manage to get this to compile.

Here is the actual error if that clarifies anything (when linked to user32.lib):

screen.obj : error LNK2019: unresolved external symbol __imp__GetSystemMetrics@4 referenced in function _getMainDisplaySize
build\lib.win32-2.6\foomodule\bitmap.pyd : fatal error LNK1120: 1 unresolved externals
error: command '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\link.exe"' failed with exit status 1120

(I am attempting to compile a Python/C module so that's why you see the weird directories)

3

There are 3 answers

2
Jerry Coffin On BEST ANSWER

You want to #include <windows.h> instead of <winuser.h>. As-is, it's probably getting some of the modifiers on the prototype wrong as it is.

Edit: since you're still having problems, perhaps we can start with a simplified test and see what you get. Fortunately, GetSystemMetrics() doesn't need a window handle or anything so e can call it from a simple console application:

#include <windows.h>
#include <iostream>

int main() { 
    size_t width = (size_t)GetSystemMetrics(SM_CXSCREEN);
    size_t height = (size_t)GetSystemMetrics(SM_CYSCREEN);

    std::cout << "width = " << width << "\n";
    std::cout << "height = " << height << std::endl; 
    return 0;
}

Here's a screen dump of compiling and running this:

D:\C\source>cl screen_res.cpp user32.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

screen_res.cpp
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:screen_res.exe
screen_res.obj
user32.lib

D:\C\source>screen_res
width = 1600
height = 1200

If this doesn't compile and run, you probably have a problem with your installation. If it does, then the problem is probably somewhere in the project you're working on.

0
sean e On

This won't help with your link error, however you also question whether that is the right way to get the display size. The params you are passing to GetSystemMetrics will not return what you want. Check the available flags at the documentation. Also consider using SystemParametersInfo. Which call to use depends on the context of what exactly you are trying to find - monitor size vs workarea, etc.

1
joeamnesiac On

The solution is to either define COMPILE_MULTIMON_STUBS in one of your modules.

#define COMPILE_MULTIMON_STUBS
#include <multimon.h>