int pixelxperinch = dc.GetDeviceCaps(LOGPIXELSX);//每英寸水平逻辑像素数
int pixelyperinch = dc.GetDeviceCaps(LOGPIXELSY);//每英寸垂直逻辑像素数
int pixelx = dc.GetDeviceCaps(HORZRES);//水平像素总数
int pixely = dc.GetDeviceCaps(VERTRES);//垂直像素总数
int hmm = dc.GetDeviceCaps(HORZSIZE);//水平毫米数
int vmm = dc.GetDeviceCaps(VERTSIZE);//垂直毫米
以上三者的关系通常满足:HORZSIZE = 25.4 * HORZRES/LOGPIXELSX
HORZSIZE为屏幕水平尺寸(定为度量尺寸,以mm计),HORZRES为水平的像素总数(定为像素大小,平时所说的屏幕分辨率,但在这不这么称呼。这里,分辨率定为“每英寸的像素数”),LOGPIXELSX为逻辑像素(假设的每英寸的像素数,并不是刚才所说的实际的“分辨率”)。因此HORZSIZE也称为逻辑宽度。
当我们选择“显示”属性里的大字体时,LOGPIXELSX(通常分为96dpi与120dpi)变大了,这样假设原来的字体为10磅,则原来的字体横向所占像素(实际所占的像素数)为10*(1/72)*LOGPIXELSX,现在LOGPIXELSX变大了,则字体所占像素也大了,因此看起来字体大了。如果HORZRES不变的话,则HORZSIZE应该变小。然而这是和Windows有关的,在16位OS中,HORZSIZE值是固定的。
在XP系统上验证了一下,发现HORZSIZE值与LOGPIXELSX的值也是不变的,如果改变HORZRES的话,则HORZSIZE会发生相应变化,但LOGPIXELSX不变,一直是96。
验证数值是:当HORZRES/VERTRES分别为800/600、1280/1024、1360/768时,LOGPIXELSX/LOGPIXELSY一直为96,但HORZSIZE/VERTSIZE分别为320/240、375/300、400/320。于是个人断定:LOGPIXELSX/LOGPIXELSY与所选的字体(如TrueType)有关,Windows默认的字体LOGPIXELSX/LOGPIXELSY值是定的,选大字体或小字体取它们的值都是一样的,而一些字体是不同的。而HORZSIZE/VERTSIZE与系统版本有关,在有的系统中,这两个值是适合此分辨率的标准显示器的尺寸(定值,长宽比与分辨率的比一样),不是通过公式计算的,也不等于公式计算的值;而有的系统版本这两个值为公式所得的值。
CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST);
pListBox->ResetContent();
//创建显示设备上下文
HDC hdc = CreateDC(_T("display"), NULL, NULL, NULL);
//颜色深度
int nBitsPerPixel=GetDeviceCaps(hdc, BITSPIXEL);
//水平分辨率
int nWidth = GetDeviceCaps(hdc, HORZRES);
//垂直分辨率
int nHeight = GetDeviceCaps(hdc, VERTRES);
//刷新率
int nDisplayFrequency = GetDeviceCaps(hdc, VREFRESH);
CString strText = _T("");
strText.Format(_T("颜色深度: %d 位"), nBitsPerPixel);
pListBox->AddString(strText);
strText.Format(_T("水平分辨率: %d 像素"), nWidth);
pListBox->AddString(strText);
strText.Format(_T("垂直分辨率: %d 像素"), nHeight);
pListBox->AddString(strText);
strText.Format(_T("刷新率: %d 赫兹"), nDisplayFrequency);
pListBox->AddString(strText);
DEVMODE DevMode;
//颜色深度
if (m_ctrlBitsPerPixel.GetCurSel() == 0)
{
DevMode.dmBitsPerPel = 16;
}
else if (m_ctrlBitsPerPixel.GetCurSel() == 1)
{
DevMode.dmBitsPerPel = 32;
}
//分辨率
if (m_ctrlPixels.GetCurSel() == 0)
{
DevMode.dmPelsWidth = 800;
DevMode.dmPelsHeight = 600;
}
else if (m_ctrlPixels.GetCurSel() == 1)
{
DevMode.dmPelsWidth = 1024;
DevMode.dmPelsHeight = 768;
}
//刷新率
if (m_ctrlDispalyFrequencry.GetCurSel() == 0)
{
DevMode.dmDisplayFrequency = 60;
}
else if (m_ctrlDispalyFrequencry.GetCurSel() == 1)
{
DevMode.dmDisplayFrequency = 75;
}
DevMode.dmSize = sizeof(DEVMODE);
DevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT |
DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
//设置显示属性
LONG nResult = ChangeDisplaySettings(&DevMode, 0);
if (nResult == DISP_CHANGE_SUCCESSFUL)
{
//用新的设置参数更新注册表
ChangeDisplaySettings(&DevMode, CDS_UPDATEREGISTRY);
AfxMessageBox(_T("设置显示属性成功。"));
}
else
{
//恢复默认设置
ChangeDisplaySettings(NULL, 0);
AfxMessageBox(_T("设置显示属性失败。"));
}
//设置显示器为省电模式
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 1);
Sleep(2000);
//打开显示器
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
Sleep(1000);
//关闭显示器
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
Sleep(2000);
//打开显示器
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
int pixelyperinch = dc.GetDeviceCaps(LOGPIXELSY);//每英寸垂直逻辑像素数
int pixelx = dc.GetDeviceCaps(HORZRES);//水平像素总数
int pixely = dc.GetDeviceCaps(VERTRES);//垂直像素总数
int hmm = dc.GetDeviceCaps(HORZSIZE);//水平毫米数
int vmm = dc.GetDeviceCaps(VERTSIZE);//垂直毫米
以上三者的关系通常满足:HORZSIZE = 25.4 * HORZRES/LOGPIXELSX
HORZSIZE为屏幕水平尺寸(定为度量尺寸,以mm计),HORZRES为水平的像素总数(定为像素大小,平时所说的屏幕分辨率,但在这不这么称呼。这里,分辨率定为“每英寸的像素数”),LOGPIXELSX为逻辑像素(假设的每英寸的像素数,并不是刚才所说的实际的“分辨率”)。因此HORZSIZE也称为逻辑宽度。
当我们选择“显示”属性里的大字体时,LOGPIXELSX(通常分为96dpi与120dpi)变大了,这样假设原来的字体为10磅,则原来的字体横向所占像素(实际所占的像素数)为10*(1/72)*LOGPIXELSX,现在LOGPIXELSX变大了,则字体所占像素也大了,因此看起来字体大了。如果HORZRES不变的话,则HORZSIZE应该变小。然而这是和Windows有关的,在16位OS中,HORZSIZE值是固定的。
在XP系统上验证了一下,发现HORZSIZE值与LOGPIXELSX的值也是不变的,如果改变HORZRES的话,则HORZSIZE会发生相应变化,但LOGPIXELSX不变,一直是96。
验证数值是:当HORZRES/VERTRES分别为800/600、1280/1024、1360/768时,LOGPIXELSX/LOGPIXELSY一直为96,但HORZSIZE/VERTSIZE分别为320/240、375/300、400/320。于是个人断定:LOGPIXELSX/LOGPIXELSY与所选的字体(如TrueType)有关,Windows默认的字体LOGPIXELSX/LOGPIXELSY值是定的,选大字体或小字体取它们的值都是一样的,而一些字体是不同的。而HORZSIZE/VERTSIZE与系统版本有关,在有的系统中,这两个值是适合此分辨率的标准显示器的尺寸(定值,长宽比与分辨率的比一样),不是通过公式计算的,也不等于公式计算的值;而有的系统版本这两个值为公式所得的值。
CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST);
pListBox->ResetContent();
//创建显示设备上下文
HDC hdc = CreateDC(_T("display"), NULL, NULL, NULL);
//颜色深度
int nBitsPerPixel=GetDeviceCaps(hdc, BITSPIXEL);
//水平分辨率
int nWidth = GetDeviceCaps(hdc, HORZRES);
//垂直分辨率
int nHeight = GetDeviceCaps(hdc, VERTRES);
//刷新率
int nDisplayFrequency = GetDeviceCaps(hdc, VREFRESH);
CString strText = _T("");
strText.Format(_T("颜色深度: %d 位"), nBitsPerPixel);
pListBox->AddString(strText);
strText.Format(_T("水平分辨率: %d 像素"), nWidth);
pListBox->AddString(strText);
strText.Format(_T("垂直分辨率: %d 像素"), nHeight);
pListBox->AddString(strText);
strText.Format(_T("刷新率: %d 赫兹"), nDisplayFrequency);
pListBox->AddString(strText);
DEVMODE DevMode;
//颜色深度
if (m_ctrlBitsPerPixel.GetCurSel() == 0)
{
DevMode.dmBitsPerPel = 16;
}
else if (m_ctrlBitsPerPixel.GetCurSel() == 1)
{
DevMode.dmBitsPerPel = 32;
}
//分辨率
if (m_ctrlPixels.GetCurSel() == 0)
{
DevMode.dmPelsWidth = 800;
DevMode.dmPelsHeight = 600;
}
else if (m_ctrlPixels.GetCurSel() == 1)
{
DevMode.dmPelsWidth = 1024;
DevMode.dmPelsHeight = 768;
}
//刷新率
if (m_ctrlDispalyFrequencry.GetCurSel() == 0)
{
DevMode.dmDisplayFrequency = 60;
}
else if (m_ctrlDispalyFrequencry.GetCurSel() == 1)
{
DevMode.dmDisplayFrequency = 75;
}
DevMode.dmSize = sizeof(DEVMODE);
DevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT |
DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
//设置显示属性
LONG nResult = ChangeDisplaySettings(&DevMode, 0);
if (nResult == DISP_CHANGE_SUCCESSFUL)
{
//用新的设置参数更新注册表
ChangeDisplaySettings(&DevMode, CDS_UPDATEREGISTRY);
AfxMessageBox(_T("设置显示属性成功。"));
}
else
{
//恢复默认设置
ChangeDisplaySettings(NULL, 0);
AfxMessageBox(_T("设置显示属性失败。"));
}
//设置显示器为省电模式
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 1);
Sleep(2000);
//打开显示器
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
Sleep(1000);
//关闭显示器
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
Sleep(2000);
//打开显示器
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, -1);