Windows平台下GTK 窗口在任务栏的隐藏问题以及解决办法
一口氣寫上了這么長(zhǎng)的一個(gè)標(biāo)題,估計(jì)嚇到不少人。這個(gè)問題并不常見,也不是一個(gè)很大很嚴(yán)重的問題。但是確實(shí)存在,并且gtk的文檔里沒有說清楚。這導(dǎo)致了我走了一些彎路。好了,進(jìn)入正題。
我們通過gtk_window_new新建一個(gè)GtkWindow后,一般情況下(不經(jīng)過我們的特殊處理),當(dāng)把這個(gè)窗口顯示出來時(shí),就會(huì)在任務(wù)欄中顯示窗口的圖標(biāo)。但是有些時(shí)候我們不想要這個(gè)圖標(biāo),比如,菜單窗口,是不應(yīng)該有這個(gè)圖標(biāo)的。
GtkWindow中提供了gtk_window_set_skip_taskbar這個(gè)函數(shù),并且有這樣的說明:"Windows may set a hint asking the desktop environment not to display the window in the task bar. This function sets this hint.”這不正是我們要的嗎?!很遺憾,在Linux上是可以的,但是在Windows上就不行了。
可以通過下面的代碼進(jìn)行驗(yàn)證:
#include
static gboolean flag = TRUE;
gboolean destroy(GtkWidget *widget, gpointer data)
{
??? gtk_main_quit();
}
gboolean clicked(GtkButton *button, gpointer data)
{
??? GtkWidget *window = (GtkWidget *)data;
??? g_print("skip taskbar:%d./n",
??????????? gtk_window_get_skip_taskbar_hint(GTK_WINDOW(window)));
??? if(flag)
??????? gtk_widget_hide_all(window);
??? else
??????? gtk_widget_show_all(window);
??? flag = !flag;
??? return FALSE;
}
int main(int argc,char ** argv )
{
??? gtk_init(&argc,&argv);
??? GtkWidget *window, *button,*layout;
??? GtkWidget *parent;
??? parent = gtk_window_new(GTK_WINDOW_TOPLEVEL);
??? window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
??? gtk_window_resize(GTK_WINDOW(window),100,200);
??? gtk_window_set_title(GTK_WINDOW(parent),"parent");
??? gtk_window_set_title(GTK_WINDOW(window),"child");???
??? gtk_window_set_decorated(GTK_WINDOW(window),FALSE);
??? gtk_widget_realize(window);
??? gtk_window_set_type_hint(GTK_WINDOW(window),GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU);
??? gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window),TRUE);
??? layout = gtk_vbox_new(FALSE,0);
??? button = gtk_button_new_with_label("ok");
??? gtk_box_pack_start(GTK_BOX(layout),button,TRUE,TRUE,0);
??? gtk_container_add(GTK_CONTAINER(parent),layout);
??? g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(clicked),window);
??? g_signal_connect(G_OBJECT(parent),"destroy",G_CALLBACK(destroy),NULL);
??? gtk_widget_show_all(window);
??? gtk_widget_show_all(parent);
??? gtk_main();
}
?
這段代碼創(chuàng)建一個(gè)窗口,然后用gtk_window_set_skip_taskbar_hint將其在任務(wù)欄中隱藏。我們可以發(fā)現(xiàn),在windows下,我們是無法通過gtk_window_set_skip_taskbar_hint函數(shù)讓窗口在任務(wù)欄中隱藏的。
其實(shí),這個(gè)問題在gtk的開發(fā)人員也是知道的。請(qǐng)看這里,https://bugzilla.gnome.org/show_bug.cgi?id=537183,但幾年過去了,問題卻沒有解決。
通過查看相關(guān)源碼,可以看到,在gtk_window_set_skip_taskbar_hint中,實(shí)際上會(huì)調(diào)用gdk_window_set_skip_taskbar_hint來完成主要的隱藏工作,而在gdk_window_set_skip_taskbar_hint函數(shù)中(在gdkwindow-win32.c文件中),讓人很意外,本質(zhì)上這個(gè)函數(shù)什么事情都沒做。所以,想通過這個(gè)函數(shù)來實(shí)現(xiàn)在任務(wù)欄中的隱藏是不可能的。
參考這個(gè)鏈接,我們可以看到,gdk的官方文檔里并不支持使用gdk_window_set_skip_taskbar_hint來隱藏任務(wù)欄圖標(biāo),它們建議使用gdk_window_set_type_hint(),由窗口類型來決定是否應(yīng)該在任務(wù)欄中顯示圖標(biāo)。
這樣做就可以了嗎?不是的。在上面的代碼中,我們看到里面已經(jīng)過窗口的類型設(shè)置成GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU(也可以使用gdk_window_set_type_hint,結(jié)果一樣),可是照樣在任務(wù)欄中可以看到這個(gè)下拉菜單的圖標(biāo)。
問題回到最初,什么樣的窗口在任務(wù)欄中是需要隱藏的?換句話說,就是什么樣的窗口在任務(wù)欄中是可以顯示的。回答這個(gè)問題暫時(shí)沒有找到windows下的明確規(guī)定,但是參考metacity的文檔中的這段話:
Dialogs which have no transient parent or root window being
their tranisent parent are the ones which will be visible in
the tasklist.
我們可以推測(cè),如果窗口不是transient 窗口,或者不是root窗口的transient 窗口,它就可以顯示在任務(wù)欄中。換言之,如果我們想讓一個(gè)窗口不顯示在任務(wù)欄中,就指定它是某一個(gè)非root窗口的transient窗口。
在我們的測(cè)試代碼中,在設(shè)置完窗口類型后,加入:
gtk_window_set_transient_for(GTK_WINDOW(window),GTK_WINDOW(parent));
現(xiàn)在,無論窗口是何種類型,都不會(huì)在任務(wù)欄中顯示了。
我們?cè)倏匆幌耮dk_window_set_skip_taskbar_hint的實(shí)現(xiàn)代碼:
void
gdk_window_set_skip_taskbar_hint (GdkWindow *window,
????????????????? gboolean?? skips_taskbar)
{
? static GdkWindow *owner = NULL;
? //GdkWindowAttr wa;
? g_return_if_fail (GDK_IS_WINDOW (window));
? GDK_NOTE (MISC, g_print ("gdk_window_set_skip_taskbar_hint: %p: %s, doing nothing/n",
?????????????? GDK_WINDOW_HWND (window),
?????????????? skips_taskbar ? "YES" : "NO"));
? // ### TODO: Need to figure out what to do here.
? return;
? if (skips_taskbar)
??? {
#if 0
????? if (owner == NULL)
??????? {
????????? wa.window_type = GDK_WINDOW_TEMP;
????????? wa.wclass = GDK_INPUT_OUTPUT;
????????? wa.width = wa.height = 1;
????????? wa.event_mask = 0;
????????? owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
??????? }
#endif
????? SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_WINDOW_HWND (owner));
#if 0 /* Should we also turn off the minimize and maximize buttons? */
????? SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
???????????? GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE) & ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU));
????? SetWindowPos (GDK_WINDOW_HWND (window), NULL,
??????????? 0, 0, 0, 0,
??????????? SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
??????????? SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
#endif
??? }
? else
??? {
????? SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, 0);
??? }
}
可以看到,作者原先的意思是如果需要skip taskbar,就為這個(gè)窗口找一個(gè)父窗口。通過下面的語句實(shí)現(xiàn):
SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_WINDOW_HWND (owner));
但是不知作者基于什么樣的原因,在類型判斷之后就return了。
也有人提出了另外的解決方法,就是通過gdk_win32_drawable_get_handle得到窗口的句柄,然后再用SetWindowLong這個(gè)Windows API來設(shè)置窗口的屬性。這種方法是也是可行的(我只試過簡(jiǎn)單的),如果做得完善的話,說不定就修正了gtk_window_set_skip_taskbar_hint無法正常使用的問題了。
總結(jié)
以上是生活随笔為你收集整理的Windows平台下GTK 窗口在任务栏的隐藏问题以及解决办法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云服务器什么配置才够用?
- 下一篇: 江苏单招C语言试题,2011年对口单招计