Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Egyre több eszköz szállít "nagy felbontású" képernyőkkel. Ezek a képernyők általában több mint 200 képpont /hüvelyk (ppi) méretűek. Az alkalmazások ezen számítógépeken való használatához a tartalmat fel kell skálázni, hogy megfeleljen a tartalom normál megtekintési távolságra való megtekintésének igényeinek. 2014-ben a nagy sűrűségű kijelzők elsődleges célja a mobil számítástechnikai eszközök (táblagépek, clamshell laptopok és telefonok).
A Windows 8.1 és újabb verziók számos funkciót tartalmaznak, amelyekkel ezek a gépek olyan kijelzőkkel és környezetekkel dolgozhatnak, ahol a gép egyszerre csatlakozik a nagy sűrűségű és a standard sűrűségű kijelzőkhöz.
A Windows lehetővé teszi a tartalomnak az eszközre való skálázását a "Szöveg és más elemek méretének növelése vagy kisebbvé tétele" beállítással (a Windows XP óta érhető el).
A Windows 8.1 és újabb verziók automatikusan skálázják a tartalmakat, hogy a legtöbb alkalmazás konzisztens legyen a különböző képpontsűrűségű kijelzők közötti áthelyezéskor. Ha az elsődleges kijelző nagy sűrűségű (200% skálázás), és a másodlagos kijelző normál sűrűségű (100%), a Windows automatikusan leskálázza az alkalmazásablak tartalmát a másodlagos kijelzőn (1 képpont az alkalmazás által megjelenített 4 képpontonként).
A Windows alapértelmezés szerint a képpontsűrűség és a megjelenítési távolság (Windows 7 és újabb, OEM-konfigurálható) megfelelő skálázása.
A Windows legfeljebb 250% képes automatikusan skálázni a tartalmat a 280 ppi-t meghaladó új eszközökön (a Windows 8.1 S14-hez hasonlóan).
A Windows a felhasználói felület vertikális felskálázásával foglalkozik a megnövekedett képpontszám kihasználása érdekében. Egy alkalmazás akkor lép be ebbe a rendszerbe, ha "rendszer DPI tudatosnak" nyilvánítja magát. Azok az alkalmazások, amelyek ezt nem teszik meg, a rendszer által felskálázásra kerülnek. Az egész alkalmazás egyenletesen szétterjedt pixelméretű, ami "homályos" felhasználói élményt eredményezhet. Például:
A Visual Studio úgy dönt, hogy a DPI skálázható, ezért nem "virtualizált".
A Windows (és a Visual Studio) számos felhasználói felületi technológiát használ, amelyek különböző módon kezelik a rendszer által meghatározott méretezési tényezőket. Például:
A WPF eszközfüggetlen módon méri a vezérlőket (egységek, nem képpontok). A WPF felhasználói felülete automatikusan felskálázódik az aktuális DPI-hez.
A felhasználói felületi keretrendszertől függetlenül minden szövegméret pontban van kifejezve, így a rendszer DPI-függetlenként kezeli őket. A Win32-, WinForms- és WPF-szövegek már megfelelően felskálázhatók, amikor a kijelzőeszközre kerülnek.
A Win32/WinForms párbeszédpanelek és ablakok lehetőséget biztosítanak olyan elrendezésekhez, amelyek szöveg alapján átméretezhetőek (például rácspanel, folyamatelem és táblázatelrendezési panelek). Ez lehetővé teszi a fixen kódolt képponthelyek elkerülését, amelyek nincsenek skálázva a betűméretek növelésekor.
A rendszer vagy az erőforrások által a rendszermetrikák alapján megadott ikonok (például SM_CXICON és SM_CXSMICON) már fel vannak skálázva.
Régebbi Win32 (GDI, GDI+) és WinForms-alapú felhasználói felület
Bár a WPF már eleve magas DPI-tudással rendelkezik, a Win32/GDI-alapú kód nagy része eredetileg nem a DPI-tudatosság szem előtt tartásával készült. A Windows DPI-méretezési API-kat biztosított. A Win32-problémák javításainak ezeket következetesen kell használniuk a terméken belül. A Visual Studio egy segédosztálytárat biztosított a funkciók duplikálásának elkerülése és a termék konzisztenciájának biztosítása érdekében.
Nagy felbontású képek
Ez a szakasz elsősorban a Visual Studio 2013-at kiterjesztő fejlesztők számára készült. Használja a Visual Studio 2015-höz beépített képszolgáltatást a Visual Studio-n belül. Azt is tapasztalhatja, hogy a Visual Studio számos verzióját támogatnia/meg kell céloznia, ezért a képszolgáltatás 2015-ös használata nem megoldás, mivel a korábbi verziókban nem létezik. Ez a szakasz önnek is szól.
Túl kicsi képek méretezése
A túl kicsi képek felskálázhatók és megjeleníthetők a GDI-n és a WPF-en néhány gyakori módszerrel. A felügyelt DPI-segédosztályok belső és külső Visual Studio-integrátorok számára érhetők el a méretezési ikonok, bitképek, képek és képlisták kezelésére. A Win32-alapú natív C/C++-segítők a HICON, a HBITMAP, a HIMAGELIST és a VsUI::GdiplusImage skálázásához érhetők el. A bitképek méretezéséhez általában csak egysoros módosítás szükséges a segédtárra mutató hivatkozás hozzáadása után. Például:
A képlista skálázása attól függ, hogy a képlista betöltéskor befejeződött-e, vagy futásidőben van hozzáfűzve. Ha a betöltési idő alatt teljesen elkészült, hívja meg a LogicalToDeviceUnits() képlistát úgy, mint egy bitképet. Ha a kódnak be kell töltenie egy egyéni bitképet a képlista írása előtt, mindenképpen skálázza fel a képlista képméretét:
imagelist.ImageSize = DpiHelper.LogicalToDeviceUnits(imagelist.ImageSize);
Natív kódban a dimenziók az alábbi módon méretezhetők a képlista létrehozásakor:
ImageList_Create(VsUI::DpiHelper::LogicalToDeviceUnitsX(16),VsUI::DpiHelper::LogicalToDeviceUnitsY(16), ILC_COLOR32|ILC_MASK, nCount, 1);
A kódtár függvényei lehetővé teszik az átméretezési algoritmus megadását. Képlistákba helyezendő képek méretezésekor ügyeljen arra, hogy adja meg az áttetszőséghez használt háttérszínt, vagy használja a NearestNeighbor skálázást (ami 125% és 150%esetén torzítást okoz).
Tekintse meg az MSDN dokumentációját DpiHelper .
Az alábbi táblázat példákat mutat be arra, hogyan kell méretezni a képeket a megfelelő DPI-méretezési tényezők alapján. A narancssárga színnel tagolt képek a Visual Studio 2013 ajánlott eljárását jelölik (100%-200% DPI-méretezés):
Elrendezési problémák
A gyakori elrendezési problémák elsősorban úgy kerülhetők el, hogy a felhasználói felületen lévő pontokat skálázva és egymáshoz viszonyítva tartják, nem pedig abszolút helyek használatával (pontosabban képpontegységekben). Például:
Az elrendezési/szövegpozícióknak igazodnia kell a felskálázott képekhez.
A rácsok oszlopainak szélességét módosítani kell a nagyított szöveghez igazodva.
A nehezen kódolt méreteket vagy az elemek közötti térközt is fel kell skálázni. A csak szövegméreteken alapuló méretek általában finomak, mert a betűtípusok automatikusan felskálázódnak.
Az DpiHelper osztályban érhetők el olyan segédfüggvények, amelyek lehetővé teszik az X és Y tengelyek skálázását.
LogicalToDeviceUnitsX/LogicalToDeviceUnitsY (a függvények lehetővé teszik a skálázást az X/Y tengelyen)
int space = DpiHelper.LogicalToDeviceUnitsX(10);
int height = VsUI::DpiHelper::LogicalToDeviceUnitsY(5);
Vannak LogicalToDeviceUnits túlterhelések, amelyek lehetővé teszik objektumok, mint a Rect, Point és Size, skálázását.
A DPIHelper könyvtár/osztály használata képek és elrendezések skálázásához
A Visual Studio DPI segédkönyvtár natív és felügyelt formában érhető el, és más alkalmazások is használhatják a Visual Studio rendszerhéján kívül.
A kódtár használatához nyissa meg a Visual Studio VSSDK bővíthetőségi mintáit , és klónozza a High-DPI_Images_Icons mintát.
A forrásfájlokban adja meg a VsUIDpiHelper.h fájlt, és hívja meg az osztály statikus függvényét VsUI::DpiHelper :
#include "VsUIDpiHelper.h"
int cxScaled = VsUI::DpiHelper::LogicalToDeviceUnitsX(cx);
VsUI::DpiHelper::LogicalToDeviceUnits(&hBitmap);
Megjegyzés:
Ne használja a segédfüggvényeket modulszintű vagy osztályszintű statikus változókban. A kódtár statikus elemet is használ a szálszinkronizáláshoz, és előfordulhat, hogy sorrend-inicializálási problémákba ütközik. Alakítsa át ezeket a statikus elemeket nem statikus tagváltozókká, vagy csomagolja őket egy függvénybe (így az első hozzáféréskor létrejönnek).
A DPI-segédfüggvények elérése a Visual Studio-környezetben futtatandó felügyelt kódból:
A fogyasztó projektnek a Shell MPF legújabb verziójára kell hivatkoznia. Például:
<Reference Include="Microsoft.VisualStudio.Shell.14.0.dll" />Győződjön meg arról, hogy a projekt a System.Windows.Formsra, a PresentationCore-ra és a PresentationUI-ra mutató hivatkozásokkal rendelkezik.
A kódban használja a Microsoft.VisualStudio.PlatformUI névteret, és hívja meg a DpiHelper osztály statikus függvényeit. A támogatott típusok (pontok, méretek, téglalapok stb.) esetében vannak olyan bővítményfüggvények, amelyek új skálázott objektumokat adnak vissza. Például:
using Microsoft.VisualStudio.PlatformUI; double x = DpiHelper.LogicalToDeviceUnitsX(posX); Point ptScaled = ptOriginal.LogicalToDeviceUnits(); DpiHelper.LogicalToDeviceUnits(ref bitmap);
A WPF-rendszerképek homályosságának kezelése nagyítható felhasználói felületen
A WPF-ben a bitképeket a WPF automatikusan átméretezi az aktuális DPI-nagyítási szinthez egy kiváló minőségű bicubic algoritmussal (alapértelmezett), amely jól működik képekhez vagy nagy képernyőképekhez, de nem megfelelő a menüelemek ikonjaihoz, mert érzékelt homályosságot mutat.
Ajánlások:
Emblémaképek és bannerek esetében az alapértelmezett BitmapScalingMode átméretező mód használható.
Menüelemekhez és ikonográfiai képekhez akkor BitmapScalingMode kell használni, ha nem okoz más torzítási összetevőket a homályosság megszüntetéséhez (200% és 300%).
Nagy nagyítási szintekhez, amelyek nem 100%-os többszörösei (például 250% vagy 350%), az ikonográfiai képek bicubic használatával történő skálázása homályos és kimosott felhasználói felületet eredményez. Jobb eredményt akkor kapunk, ha először 100% (például 200% vagy 300%) legnagyobb többszörösére skálázjuk a képet a NearestNeighborral, majd onnan skálázjuk a bikubicot. További információkért lásd a speciális esetet: WPF-rendszerképek előskálázása nagy DPI-szintekhez.
A Microsoft.VisualStudio.PlatformUI névtér DpiHelper osztálya egy kötéshez használható tagot BitmapScalingMode biztosít. Lehetővé teszi, hogy a Visual Studio rendszerhéj a DPI skálázási tényezőtől függően egységesen vezérelje a bitkép skálázási módját a terméken belül.
Ha xAML-ben szeretné használni, adja hozzá a következőt:
xmlns:vsui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.14.0"
<Setter Property="RenderOptions.BitmapScalingMode" Value="{x:Static vs:DpiHelper.BitmapScalingMode}" />
A Visual Studio grafikus felülete már beállítja ezt a tulajdonságot a legfelső szintű ablakokra és párbeszédpanelekre. A Visual Studióban futó WPF-alapú felhasználói felület már örökli azt. Ha a beállítás nem propagálható az adott felhasználói felületen, akkor az XAML/WPF felhasználói felület gyökérelemén állítható be. Ilyenek azok a helyek, ahol ez történik: előugró ablakok, a Win32-szülőkkel rendelkező elemek, valamint a külön folyamatban futó tervezőablakok, például a Blend.
Egyes felhasználói felületek a rendszer által beállított DPI nagyítási szinttől függetlenül méretezhetők, például a Visual Studio szövegszerkesztőjétől és a WPF-alapú tervezőktől (WPF Desktop és Windows Áruház). Ezekben az esetekben a DpiHelper.BitmapScalingMode nem használható. A hiba a szerkesztőben való megoldásához az IDE csapata létrehozott egy egyéni tulajdonságot RenderOptions.BitmapScalingMode néven. Állítsa be ezt a tulajdonságértéket HighQuality vagy NearestNeighbor értékre a rendszer és a felhasználói felület együttes nagyítási szintjétől függően.
Speciális eset: WPF-rendszerképek előskálázása nagy DPI-szintekhez
Nagyon nagy nagyítási szintek esetén, amelyek nem többszörösei a 100% (például 250%, 350%stb.), az ikonográfiai képek bicubic skálázása homályos, kimosott felhasználói felületet eredményez. Ezeknek a képeknek a benyomása a ropogós szöveg mellett majdnem olyan, mint egy optikai illúzió. Úgy tűnik, hogy a képek közelebb kerülnek a szemhez, és a szöveghez képest homályosak vagy elmosódottak. A méretezési eredmény ezen a nagyított méreten javítható, ha először 100% (például 200% vagy 300%) legnagyobb többszörösére skálázza a képet a NearestNeighborral, majd a többihez bicubic-sel skáláz (további 50%).
** Az alábbi példa az eredmények különbségeit szemlélteti, ahol az első kép skálázása a továbbfejlesztett kétszeres skálázási algoritmussal történik 100%->200%->250%, a második pedig csak bicubikus módszerrel 100%->250%.
Ahhoz, hogy a felhasználói felület használhassa ezt a kettős méretezést, módosítani kell az egyes képelemek megjelenítéséhez szükséges XAML-jelöléseket. Az alábbi példák bemutatják, hogyan használható a dupla skálázás a WPF-ben a Visual Studióban a DpiHelper könyvtár és a Shell.12/14 használatával.
1. lépés: A kép előskálázása 200%, 300%, és így tovább a NearestNeighbor használatával.
A kép előzetes méretezése történhet kötésen alkalmazott konverterrel vagy XAML jelölő bővítménnyel. Például:
<vsui:DpiPrescaleImageSourceConverter x:Key="DpiPrescaleImageSourceConverter" />
<Image Source="{Binding Path=SelectedImage, Converter={StaticResource DpiPrescaleImageSourceConverter}}" Width="16" Height="16" />
<Image Source="{vsui:DpiPrescaledImage Images/Help.png}" Width="16" Height="16" />
Ha a képet is témázni kell (a legtöbb esetben így van), a jelölőnyelv használhat egy másik átalakítót, amely először elvégzi a kép témázását, majd az előszerkesztést a méretek előzetes beállításával. A jelölés a kívánt konverziós kimenettől függően használhatja vagy a DpiPrescaleThemedImageConverter vagy a DpiPrescaleThemedImageSourceConverter tag-et.
<vsui:DpiPrescaleThemedImageSourceConverter x:Key="DpiPrescaleThemedImageSourceConverter" />
<Image Width="16" Height="16">
<Image.Source>
<MultiBinding Converter="{StaticResource DpiPrescaleThemedImageSourceConverter}">
<Binding Path="Icon" />
<Binding Path="(vsui:ImageThemingUtilities.ImageBackgroundColor)"
RelativeSource="{RelativeSource Self}" />
<Binding Source="{x:Static vsui:Boxes.BooleanTrue}" />
</MultiBinding>
</Image.Source>
</Image>
2. lépés: Győződjön meg arról, hogy a végső méret helyes az aktuális DPI-hez.
Mivel a WPF az aktuális DPI-nek megfelelően skálázza a felhasználói felületet a UIElement-en beállított BitmapScalingMode tulajdonsággal, egy olyan Image vezérlő, amely előre skálázott képet használ forrásként, a kelleténél kétszer vagy háromszor nagyobbnak fog tűnni. Az alábbiakban néhány módszert kínálunk ennek a hatásnak a elhárítására:
Ha ismeri az eredeti kép 100%-os méretét, megadhatja a képvezérlő pontos méretét. Ezek a méretek a skálázás alkalmazása előtt tükrözik a felhasználói felület méretét.
<Image Source="{Binding Path=SelectedImage, Converter={StaticResource DpiPrescaleImageSourceConverter}}" Width="16" Height="16" />Ha az eredeti kép mérete nem ismert, az LayoutTransform segítségével leskálázható a végső képobjektum. Például:
<Image Source="{Binding Path=SelectedImage, Converter={StaticResource DpiPrescaleImageSourceConverter}}" > <Image.LayoutTransform> <ScaleTransform ScaleX="{x:Static vsui:DpiHelper.PreScaledImageLayoutTransformScale}" ScaleY="{x:Static vsui:DpiHelper.PreScaledImageLayoutTransformScale}" /> </Image.LayoutTransform> </Image>
A HDPI támogatásának engedélyezése a WebOC-hez
A WebOC-vezérlők (például a WPF WebBrowser vezérlője vagy az IWebBrowser2 felület) alapértelmezés szerint nem engedélyezik a HDPI észlelését és támogatását. Az eredmény egy beágyazott vezérlő lesz, amelynek megjelenítési tartalma túl kicsi a nagy felbontású kijelzőn. Az alábbiakban bemutatjuk, hogyan engedélyezhet magas DPI-támogatást egy adott webOC-példányban.
Implementálja az IDocHostUIHandler felületet (lásd az MSDN-cikket az IDocHostUIHandlerről:
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("BD3F23C0-D43E-11CF-893B-00AA00BDCE1A")]
public interface IDocHostUIHandler
{
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int ShowContextMenu(
[In, MarshalAs(UnmanagedType.U4)] int dwID,
[In] POINT pt,
[In, MarshalAs(UnmanagedType.Interface)] object pcmdtReserved,
[In, MarshalAs(UnmanagedType.IDispatch)] object pdispReserved);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetHostInfo([In, Out] DOCHOSTUIINFO info);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int ShowUI(
[In, MarshalAs(UnmanagedType.I4)] int dwID,
[In, MarshalAs(UnmanagedType.Interface)] object activeObject,
[In, MarshalAs(UnmanagedType.Interface)] object commandTarget,
[In, MarshalAs(UnmanagedType.Interface)] object frame,
[In, MarshalAs(UnmanagedType.Interface)] object doc);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int HideUI();
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int UpdateUI();
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int EnableModeless([In, MarshalAs(UnmanagedType.Bool)] bool fEnable);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int OnDocWindowActivate([In, MarshalAs(UnmanagedType.Bool)] bool fActivate);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int OnFrameWindowActivate([In, MarshalAs(UnmanagedType.Bool)] bool fActivate);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int ResizeBorder(
[In] COMRECT rect,
[In, MarshalAs(UnmanagedType.Interface)] object doc,
bool fFrameWindow);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int TranslateAccelerator(
[In] ref MSG msg,
[In] ref Guid group,
[In, MarshalAs(UnmanagedType.I4)] int nCmdID);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetOptionKeyPath(
[Out, MarshalAs(UnmanagedType.LPArray)] string[] pbstrKey,
[In, MarshalAs(UnmanagedType.U4)] int dw);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetDropTarget(
[In, MarshalAs(UnmanagedType.Interface)] IOleDropTarget pDropTarget,
[MarshalAs(UnmanagedType.Interface)] out IOleDropTarget ppDropTarget);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetExternal([MarshalAs(UnmanagedType.IDispatch)] out object ppDispatch);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int TranslateUrl(
[In, MarshalAs(UnmanagedType.U4)] int dwTranslate,
[In, MarshalAs(UnmanagedType.LPWStr)] string strURLIn,
[MarshalAs(UnmanagedType.LPWStr)] out string pstrURLOut);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int FilterDataObject(
IDataObject pDO,
out IDataObject ppDORet);
}
Igény szerint implementálhatja az ICustomDoc felületet (lásd az MSDN-cikket az ICustomDoc-ról:
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("3050F3F0-98B5-11CF-BB82-00AA00BDCE0B")]
public interface ICustomDoc
{
void SetUIHandler(IDocHostUIHandler pUIHandler);
}
Társítsa az IDocHostUIHandlert megvalósító osztályt a WebOC dokumentumához. Ha az ICustomDoc felületet implementálta a fentiek szerint, akkor amint a WebOC dokumentum tulajdonsága érvényes lesz, ezt alakítsa át ICustomDoc-ká, majd hívja meg a SetUIHandler metódust, az IDocHostUIHandlert implementáló osztályt továbbítva argumentumként.
// "this" references that class that owns the WebOC control and in this case also implements the IDocHostUIHandler interface
ICustomDoc customDoc = (ICustomDoc)webBrowser.Document;
customDoc.SetUIHandler(this);
Ha NEM implementálta az ICustomDoc felületet, akkor amint a WebOC dokumentum tulajdonsága érvényes, le kell képeznie egy IOleObject-re, és meg kell hívnia a SetClientSite metódust, az IDocHostUIHandler-t implementáló osztályt megadva. Állítsa be a DOCHOSTUIINFO-ban a metódushívás során átadott DOCHOSTUIFLAG_DPI_AWARE jelzőt.
public int GetHostInfo(DOCHOSTUIINFO info)
{
// This is what the default site provides.
info.dwFlags = (DOCHOSTUIFLAG)0x5a74012;
// Add the DPI flag to the defaults
info.dwFlags |=.DOCHOSTUIFLAG.DOCHOSTUIFLAG_DPI_AWARE;
return S_OK;
}
Csak ennyire van szüksége, hogy a WebOC vezérlő támogassa a HPDI-t.
Tippek
Ha a WebOC-vezérlő dokumentumtulajdonságai módosulnak, előfordulhat, hogy újra kell társítania a dokumentumot az IDocHostUIHandler osztálysal.
Ha a fentiek nem működnek, ismert probléma merül fel azzal kapcsolatban, hogy a WebOC nem veszi fel a DPI-jelző módosítását. Ennek a megoldásnak a legmegbízhatóbb módja a WebOC optikai nagyításának kapcsolása, vagyis két hívást kell kezdeményezni két különböző nagyítási százalékértékkel. Emellett, ha ez a kerülő megoldás szükséges, szükség lehet rá minden navigálási híváson.
// browser2 is a SHDocVw.IWebBrowser2 in this case // EX: Call the Exec twice with DPI%-1 and then DPI% as the zoomPercent values IOleCommandTarget cmdTarget = browser2.Document as IOleCommandTarget; if (cmdTarget != null) { object commandInput = zoomPercent; cmdTarget.Exec(IntPtr.Zero, OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, ref commandInput, ref commandOutput); }