【问题标题】:Is it possible to find the screen resolution from within a C program under Linux?是否可以在 Linux 下的 C 程序中找到屏幕分辨率?
【发布时间】:2018-02-17 05:13:35
【问题描述】:

我知道我可以使用 xdpyinfo 从 Linux 上的命令行获取屏幕分辨率,但是否也可以在 C 程序中执行此操作?如果有怎么办?

【问题讨论】:

  • 当然有可能,操作系统是用 C 语言编写的。查找您系统的相关文档,标准 C 语言没有任何帮助。
  • 当然,您认为xdpyinfo 是如何获取信息的?这是它的源代码,你可以看看它是怎么做的:cgit.freedesktop.org/xorg/app/xdpyinfo/tree/xdpyinfo.c。但我警告你,裸 X11 库并不好用。
  • @DeiDei 当然标准 C 没有解决这个问题。这不是我要问的。我正在寻找一种通用的 Linux 解决方案,而不仅仅是我的系统。如果您知道任何相关文件,请发布信息。
  • 一般的解决方案是使用 libX11 或 libX11 的包装器,如 GTK+ 或 Qt。他们可能有这些函数的包装器,以便更容易地获取这些信息。但是看xdpyinfo的代码,不长也不复杂。
  • 我认为您可能想要链接并使用 Xrandr 库。命令行实用程序是 'xrandr -q'

标签: c linux screen screen-resolution


【解决方案1】:

遵循@Pablo 的建议(感谢 Pablo!)我能够破解 xdpyinfo.c 以获得我想要的东西。演示代码为:

#ifdef WIN32
#include <X11/Xwindows.h>
#endif

#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>

static void
print_screen_info(Display *dpy, int scr)
{
    /*
     * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
     *
     *     dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
     *         = N pixels / (M inch / 25.4)
     *         = N * 25.4 pixels / M inch
     */

    double xres, yres;

    xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) /
            ((double) DisplayWidthMM(dpy,scr)));
    yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) /
            ((double) DisplayHeightMM(dpy,scr)));

    printf ("\n");
    printf ("screen #%d:\n", scr);
    printf ("  dimensions:    %dx%d pixels (%dx%d millimeters)\n",
            XDisplayWidth (dpy, scr),  XDisplayHeight (dpy, scr),
            XDisplayWidthMM(dpy, scr), XDisplayHeightMM (dpy, scr));
    printf ("  resolution:    %dx%d dots per inch\n",
            (int) (xres + 0.5), (int) (yres + 0.5));
}


int
main(int argc, char *argv[])
{
    Display *dpy;                        /* X connection */
    char *displayname = NULL;            /* server to contact */
    int i;                      

    dpy = XOpenDisplay (displayname);
    if (!dpy) {
        fprintf (stderr, "unable to open display \"%s\".\n",
                 XDisplayName (displayname));
        exit (1);
    }

    printf ("name of display:    %s\n", DisplayString (dpy));
    printf ("default screen number:    %d\n", DefaultScreen (dpy));
    printf ("number of screens:    %d\n", ScreenCount (dpy));

    for (i = 0; i < ScreenCount (dpy); i++) {
        print_screen_info (dpy, i);
    }

    XCloseDisplay (dpy);
    exit (0);
}

编译:

gcc test.c -lX11

输出如下:

erpsim1:~/linux_lib/test> ./a.out 
name of display:    localhost:15.0
default screen number:    0
number of screens:    1

screen #0:
  dimensions:    4400x1400 pixels (1552x494 millimeters)
  resolution:    72x72 dots per inch

【讨论】:

    【解决方案2】:

    如果xdpyinfo 适合您,请使用它。创建一些管道,fork(),连接管道,然后 exec(xdpyinfo) 这比找出 libX11 容易得多;有人已经为你完成了这项工作。这不是我要使用的成语,但它传达了这个想法:

    int filedes[2];
    if (pipe(filedes) == -1) {
      perror("pipe");
      exit(1);
    }
    
    pid_t pid = fork();
    if (pid == -1) {
      perror("fork");
      exit(1);
    } else if (pid == 0) {
      while ((dup2(filedes[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
      close(filedes[1]);
      close(filedes[0]);
      execl(cmdpath, cmdname, (char*)0);
      perror("execl");
      _exit(1);
    }
    close(filedes[1]);
    

    while(...EINTR)) 循环只是在文件描述符关闭和复制期间防止中断。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多