【问题标题】:Custom icon not displayed in upper left corner or on task bar自定义图标不显示在左上角或任务栏上
【发布时间】:2010-10-04 22:24:03
【问题描述】:

我已经使用 windows api 创建了一个基本应用程序。它只是显示一个小窗口。我从主函数开始,获取实例,创建我的 windows 类等。一切正常。然而,我遇到的问题是我的自定义图标不会显示在窗口的左上角或任务栏上,它只显示窗口的默认小图片。但是,它确实显示为我的实际可点击 exe 文件的图标。我使用 resedit 来制作我的资源,并创建了所有 4 种图标大小,因此它应该有一个可用的适当大小。我掌握了

HICON hMyIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));

然后我使用 WNDCLASSEX 并将句柄交给 hIcon 和 hIconsm。 如果有什么可能导致它不显示在角落或任务栏中,请帮助。

#include <Windows.h>
#include <iostream>
#include "resource.h"
//globals
    MSG msg;
    HWND hwndwnd;
    HICON hMyIcon;
//Windows Procedure
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
    switch ( message )
    {
    case WM_CLOSE:    
        exit( 0 );
        break;    
    case WM_CREATE:
        SendMessage(hwndwnd,WM_SETICON,ICON_SMALL,(LPARAM)hMyIcon);
        break;
    }
    return DefWindowProc( hwnd, message, wparam, lparam );
}

int main(int ArgumentNum, char *arg[])
{
    //get instance
    char title[500];
    GetConsoleTitleA( title, 500 );
    HWND hwndConsole = FindWindowA( NULL, title );
    HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hwndConsole, GWLP_HINSTANCE);
    //get icon handle
    hMyIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
    if (hMyIcon == NULL)
    {
         std::cout<< "NULL\n";
    }
    //create & register class
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_DROPSHADOW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = hMyIcon;
    wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
    wc.lpszMenuName = 0;
    wc.lpszClassName = "Jacob";
    wc.hIconSm = hMyIcon;
    RegisterClassEx(&wc);
    //create window
    hwndwnd = CreateWindow("Jacob", "My Window", 
    WS_OVERLAPPEDWINDOW, 520, 20, 300, 300, NULL, NULL, hInstance, NULL);
    //Tried sendmessage here as well
    //SendMessage(hwndwnd,WM_SETICON,ICON_SMALL,(LPARAM)hMyIcon);
    ShowWindow( hwndwnd, SW_SHOWNORMAL);
    UpdateWindow( hwndwnd );
    //hide console, not using to see if icon is null
    //ShowWindow( hwndConsole, 0 );
    //message loop
    while(GetMessage( &msg, hwndwnd, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

这是我的源代码。我开始怀疑我的问题是否与我的资源有关。当我使用 resedit 时,我为各种可能大小的图标疯狂。希望这会有所帮助,并感谢您的耐心等待。

【问题讨论】:

  • assert(hMyIcon != NULL);

标签: c++ winapi icons


【解决方案1】:

我的第一个建议是尝试加载标准图标而不是您自己的图标:

hMyIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ERROR));

这应该可行,您应该会看到红色的错误消息图标。

接下来要做的是尝试以不同的方式获取实例句柄。控制台窗口是一个奇怪的品种,不要将它们与 Win32 API 的其余部分混合太多。试试:

hInstance = GetModuleHandle(NULL);

【讨论】:

  • WOOOOOO,它有效,GetModuleHandle 函数返回的实例与我使用的方法返回的实例有何不同?
  • @Jake:因为控制台窗口与普通窗口完全不同。 “窗口”本身位于一个单独的系统进程 (CSRSS) 中,尝试在其上使用标准 API 函数不会得到预期的结果。阅读this article 了解一些相关历史。
【解决方案2】:
  • 您确定您的 LoadIcon 调用返回 != NULL 吗?
  • Lo​​adIcon 总是加载一个 32x32 的图标,MSDN 说如果 hIconSm 为 NULL,它会检查图标资源中是否有正确大小的图标,所以也许你应该尝试设置 hIconSm=NULL;
  • 你可以使用WM_SETICON

编辑:

//(Having your code from the start would have made things easier)
#include <Windows.h>
#include "resource.h"
MSG msg;
HWND hwndwnd;
HICON hMyIcon;

LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
    switch ( message )
    {
    case WM_CLOSE:    
        DestroyWindow(hwnd);//exit( 0 );
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_CREATE:
//        SendMessage(hwndwnd,WM_SETICON,ICON_SMALL,(LPARAM)hMyIcon);
        break;
    }
    return DefWindowProc( hwnd, message, wparam, lparam );
}


int main(int ArgumentNum, char *arg[]) 
{
/*
    You don't own/control the console window, don't use it's HWND if you don't have to.
    ...And there is even a function to get the HWND if you need it, no need for FindWindow

    char title[500];
    GetConsoleTitleA( title, 500 );
    HWND hwndConsole = FindWindowA( NULL, title );
    HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hwndConsole, GWLP_HINSTANCE);
    */
    HINSTANCE hInstance=GetModuleHandle(NULL);
    hMyIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_DROPSHADOW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = hMyIcon;
    wc.hCursor = LoadCursor(/*hInstance*/NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
    wc.lpszMenuName = 0;
    wc.lpszClassName = "Jacob";
#if 1 //The easy way
    wc.hIconSm = NULL;//hMyIcon; LoadIcon only loads 32x32 icons, you would get the wrong icon
#else //The hard way
    wc.hIconSm = (HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_ICON1),IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0);
#endif
    RegisterClassEx(&wc);
    //create window
    hwndwnd = CreateWindow("Jacob", "My Window", 
    WS_OVERLAPPEDWINDOW, 520 , 20, 300, 300, NULL, NULL, hInstance, NULL);
    ShowWindow(hwndwnd,SW_SHOW);
    while(GetMessage( &msg, /*hwndwnd*/NULL, 0, 0) >0 ) //normally not a good idea to specify a hwnd
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

【讨论】:

  • 我已经确定它不会返回 NULL if (hMyIcon == NULL) { std::cout
  • 在 CreateWindow 之后,执行 SendMessage(yourwindow,WM_SETICON,ICON_SMALL,(LPARAM)youriconhandle); (也可以这样设置大图标)
  • 我也试过了。这可能与我不使用 winmain 函数有什么关系,因为我注册了我的类并在 main 函数中创建了我的窗口,所以我需要 winmain 才能工作吗?你想让我编辑我的帖子并把我的来源放进去吗?
  • 不,你不需要 WinMain,但你需要一个消息循环。发布您的代码可能会有所帮助
  • 知道了,谢谢大家的帮助,非常感谢。现在是时候开始阅读我的新书《游戏引擎架构》了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-14
  • 2020-03-31
相关资源
最近更新 更多