作者: admin

  • 違法噴灑遭禁殺蟲劑 孟山都將付3億罰款

    摘錄自2019年11月22日中央通訊社美國報導

    美國農業生技巨擘孟山都(Monsanto)今天(22日)同意認罪,承認在夏威夷毛伊島(Maui)的設施對研究作物違法噴灑遭禁的劇毒殺蟲劑,將支付1000萬美元(約新台幣3億532萬元)罰款。

    法新社報導,孟山都在提交給檀香山聯邦地區法院的法庭文件中承認,2014年在農場谷(Valley Farm)對玉米種子等作物噴灑Penncap-M殺蟲劑,即使已知環境保護署於2013年禁用這款化學物。

    審理此案的加州中區聯邦檢察官韓納(Nick Hanna)說:「此案的違法行徑對環境、周圍社區和孟山都工人構成威脅。」他說:「聯邦法律與相關規範規定,使用管制和危險化學物的每個人,都有責任確保產品是經過安全儲存、運送與使用。」

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※南投搬家前需注意的眉眉角角,別等搬了再說!

    ※新北清潔公司,居家、辦公、裝潢細清專業服務

  • 新宿市民測定所 發表嬰幼兒奶粉輻射檢查報告

    文:宋瑞文(媽媽監督核電廠聯盟特約撰述)

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※別再煩惱如何寫文案,掌握八大原則!

  • 一口氣投80億人民幣 比亞迪建長沙、青島兩個新能源車生產基地

    比亞迪汽車於5月18日與湖南省長沙市雨花區經開區簽署合作備忘錄,比亞迪將投資50億元人民幣(下同),在長沙比亞迪汽車城二期興建電動卡車及專用車生產基地,計畫年內投產。   長沙比亞迪專案將由電動轎車、電動客車和電動卡車及專用車三部分組成。電動卡車及專用車專案,現已動工建設,是比亞迪電動卡車及專用車全球製造中心,含整車及相應配套零部件,目標向全中國工廠提供電動底盤、車橋等核心部件。比亞迪預計2016年將達產2500輛,規劃至2020年達5000輛年產能,2025年擴建到10000輛年產能。   此外,比亞迪在青島市城陽區投資30億元的新能源汽車專案一期目前已開工建設,這是青島城陽首個新能源汽車產業專案,也是建區以來引進的最大工業專案。根據規劃分三期建設完成,預計2017年全部建成。專案全部建成後,將年產電動汽車5000輛,年可實現銷售收入105億元。   此專案位於棘洪灘軌道交通裝備製造產業園內,規劃佔地1000畝,主要生產純電動轎車、中巴、小巴、物流車等產品,以及從事車輛電池、電機、電控等核心零部件的研發和製造。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • 比亞迪新能源車夯!2015年可望售出350億人民幣

    根據中國汽車工業協會公佈的統計資料顯示,2015年1至4月份,比亞迪新能源汽車銷量已超過1.2萬輛。同時第一季,比亞迪歸屬於上市公司股東的淨利潤達1.2億元人民幣(下同),同比增幅高達910%。   按4月份單月的銷量資料來看,比亞迪乘用車總體銷量為32260輛,年減29.85%。但新能源汽車銷量為3646輛,其中秦2625輛,e6電動車890輛,騰勢131輛,實現了正向增長。   據比亞迪相關人士介紹,2015年,比亞迪還將推出包括鎖定個人消費者的插電式混合動力汽車「唐」,中型及緊湊型插電式混合動力SUV車型「宋」和「元」,以及新能源商用車「商」等。除此之外,在特種車輛方面,比亞迪也會逐步加快研發並推出應用於礦山、港口、機場及倉儲等領域的車型,以及應用於環衛、城市物流等領域的特種車輛。   而比亞迪副總裁廉玉波在出席內地電動車研討會時透露,預料今年可售出約值300億元至350億元的新能源汽車,料全年可售出約6.7萬部新車,佔公司汽車業務一半收入,並有望達到「自給自足」盈利水準。   他表示,現時比亞迪每月可售出1,000部純電動車e6,純電動巴士每月售約600部。且位於惠州的電池廠3月起投產,有利提升產能;其中較受歡迎的混能車「秦」,6月時產能將增至6,000架。而比亞迪與戴姆勒合資生意的純電動車「騰勢」,每月約售出500部,估計年底時將增至3,000至4,000部。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    ※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

    ※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!

    ※新北清潔公司,居家、辦公、裝潢細清專業服務

  • Tesla 挹注擴大 F-貿聯第三季營收季增幅度大

    Tesla 日前發表的儲能電池計畫,受到外界關注,法人評估,首波供應商 F-貿聯最快 8 月有機會開始交貨,明年下半年新計畫挹注逐步擴大。法人也預估,該公司本季營收季增個位數、且將挑戰單季新高,第三季起隨 Tesla 新 SUV 車款問世,6 月下旬起零件逐月放量,下季營收季增幅度將拉大,全年營收拚增兩位數。   F-貿聯與 Tesla 的往來關係深厚,早在 Tesla 還未成為全球知名的電動車大廠前,就已相互搭配,因此也成為該客戶的指標核心供應商。一直以來,貿聯較為人熟知是 Tesla 電動車電池管理系統線束的獨家供應商,此次配合與松下合資的超級電池工廠明年下半年量產,電池供應量將大增。   據了解,F-貿聯已是特斯拉除能電池系統 Powerwall 與企業用 Powerpack 計畫的首波零件供應商,供貨品項仍為電池管理系統用線。法人預期,最快 8 月有望正式交貨,雖對今年的營收貢獻不大,但更確認了貿聯在 Tesla 各項計畫共同開發的核心地位,而明年下半年超級電池工廠如果順利量產,該計畫的挹注將明顯增溫。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    ※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

  • 詳解電動汽車無線充電技術

    詳解電動汽車無線充電技術

    Q1:無線充電有哪些方式?原理是什麼?  

      A:現在劃分的無線充電類型有好些種,比如感應式、共振式、微波傳輸式等等,不過總體來說,它們的基本原理都是一樣的,就是利用交變電磁場的電磁感應,來實現能量的無線傳輸。    感應式的無線電能傳輸算是目前比較成熟的技術,很多手機無線充電、甚至我們常見的電磁爐就是利用的這種原理。由於數碼設備空間小,接收線圈也小,加上充電設備功率小,所以通常充電的距離近(甚至需要與充電座接觸),不過相對電磁輻射也小。    共振式則是麻省理工目前在開發的一類充電技術,說起來也不複雜,他們利用電磁感應現象,加上共振的原理,能提升無線充電的效率。共振傳輸的距離比普通感應式更遠一些,而麻省理工目前正在進行小型化的研究——對於車長好幾米的電動車來說,這方面的技術壓力倒不是太大。    微波傳輸式此前更多出現在科幻電影或者小說裡面,實際上它也是無線電力傳輸的一個很好的方式,只不過受到發送功率等方面的限制,並未大規模實用化。微波傳輸的最大好處就是傳輸距離遠,甚至可以實現航天器與地面之間的能量傳輸,同時還可以實現定向傳輸(發射天線有方向性),未來前景值得期待。  

     

    Q2:無線充電的好處有哪些?

      A:無線充電的第一個好處就是不需要線,不必為了到處找充電線而費神。第二就是無線充電在硬體方面的標準更容易統一。  
    Q3:有待解決的問題有哪些?   A: 一、傳輸效率是所有無線充電都面臨的問題,對於電動車這樣充電功率更大的“電器”來說更是如此——電能首先轉換為無線電波,再由無線電波轉換成電能,這兩次轉換都會損失不少的能量。   二、電磁相容也是無線充電需要解決的技術瓶頸之一。電磁波很容易產生洩漏,當大功率的車用無線充電設備運行時,也會對周圍的生物和電子設備產生影響,甚至會危害人體健康。利用封閉的自動智慧化車庫安裝無線充電設備是解決電磁相容比較好的途徑,不過成本也確實不菲。   三、電氣標準等方面的問題。  
    Q4:有哪些典型案例呢?   A:從國外車企來看,特斯拉、沃爾沃、奧迪、寶馬、賓士等傳統汽車都已經開始研發或測試旗下電動車的無線充電系統。全球通訊以及IT界的新貴們也將“觸角”伸向了電動車無線充電的新領域。而在無線充電的規劃和靜態還是動態充電的選擇上,國內外車企則各有不同。  
    一、沃爾沃:利用道路進行無線充電  

      在瑞典,沃爾沃集團、瑞典電力公司 Alstom、瑞典能源局正在共同合作測試利用公路給電動汽車充電,通過將兩個電源線鋪設在公路上,電動車經過時便可獲得電力供應。這項技術的核心在於汽車得搭載集電器,集電器與公路上的電纜連線,利用直流電充電。汽車不必走在電纜的中央,但必須時速大於 60 公里。    沃爾沃已在瑞典的 H llered 測試中心建立了一條 1/4 英里長的軌道,用一輛卡車進行測試。未來,當電動汽車需要充電時,必須安裝無線發射器讓道路感知,然後經過加密信號啟動充電功能。由於對速度有要求,沃爾沃的這一充電系統適合在高速路上實行,如果未來成真,人們出遠門的時候就不用擔心電力問題。   利用公路地表進行無線充電很可能是未來的發展方向,相比地面上的設施,它的好處是不需要佔用地面空間,可減少建設、維護成本。汽車不需要停下來進行充電,可持續駕駛。   沃爾沃的這一舉措是為了給電動汽車打造一個良好的充電網路。不過它需要面對很多普及的問題,比如公路建設、設計問題、集電器、電動汽車的支持等。就像無人駕駛一樣,這是一個浩大的工程,短期內還難以實現。  
    二、高通:Halo的感應充電系統  

      在2015年4月22日的Formula E電動方程式錦標賽上,高通就展示了自己研發的Halo無線汽車充電技術。只要將車開到充電墊的正上方,當充電線圈對齊之後,電流便會開始輸送到汽車當中。如果汽車和墊子之間存在外來物體,系統還可自動暫停充電。   高通Halo的感應充電系統是個相對直接明瞭的構想:一個由兩個鐵氧體組成的變壓器,兩者的旁邊還各有一個電線線圈。一般來講,這兩個部分是連接在一起的。交流電會在第一個線圈中被轉換成磁場,隨後再被第二個線圈轉換成直流電。而高通Halo卻將兩個鐵氧體分離開來,並讓系統跨越空氣間隔實現最大功率傳輸。    Halo的無線充電器被放置在了車尾的位置,是一個比機上盒稍大一些的金屬盒子,並連接著幾條橙色的電線。至於另一半的充電器,就在汽車的下方。感應充電其實是可以作用於移動中的車輛的。Halo目前已經具備了半動態充電的能力,可在最高30mph的速度下進行電能傳輸。  
    三、日產無線充電汽車   日產魔方電動車採用了可在供電線圈和受電線圈之間提供電力的電磁感應方式。即將一個受電線圈裝置安裝在汽車的底盤上,將另一個供電線圈裝置安裝在地面,當電動汽車駛到供電線圈裝置上,受電線圈即可接受到供電線圈的電流,從而對電池進行充電。目前,這套裝置的額定輸出功率為 10kW,一般的電動汽車可在7-8小時內完成充電。    日本無線充電式混合動力巴士:電磁感應式,供電線圈是埋入充電台的混凝土中的。車開上充電台後,當車載線圈對準供電線圈後(重合),車內的儀錶板上有一個指示燈會亮,司機按一下充電按鈕,就開始充電。   
    三、中興:無線供電系統   中興通訊的無線供電系統是通過非接觸的電磁感應方式進行電力傳輸。當充電車輛在充電停車位停泊後,就能自動通過無線接入充電場的通信網路,建立起地面系統和車載系統的通信鏈路,並完成車輛鑒權和其他相關資訊交換。   充電位元也可以通過有線或者無線的方式和雲服務中心進行互聯。一旦出現充電和受電的任何隱患,地面充電模組將立即停止充電並報警,確保充電過程安全可靠。最重要的是,無線充電系統在車輛運行時完全不工作,即使車輛在上面駛過,或者在雷雨等惡劣天氣情況下,也能確保安全。  
    四、比亞迪:WAVE無線充電墊   比亞迪早在2005年12月就申請了非接觸感應式充電器專利。在2014年7月賣給猶他大學一輛40英尺的純電動巴士,這款巴士就裝配著最新的WAVE無線充電墊。  
    五、奧迪:可升降的無線充電系統   奧迪的可升降的無線充電系統最大的特點就是可讓供電線圈更靠近車輛底部的受電線圈,實現了超過90%的電力傳輸效率。這種方式能讓一些高底盤的SUV在充電時保證更好的充電效率。奧迪的無線充電技術僅需要使用者將停車位元元上安置一塊配置線圈和逆變器(AC/AC)充電板,並連接至電網,當車輛停在電板上時,充電過程會自動開啟。   這種充電的原理是充電板內的交變磁場將3.3千瓦的交變電流感應至集成在車內次級線圈的空氣層中,實現電網電流逆向並輸入到車輛的充電系統中。當電池組充滿電時,充電將自動中止。感應式無線充電所需的充電時間與電纜充電所需的充電時間大致相同,且用戶可以隨時中斷充電並使用車輛。   奧迪的無線充電技術效率超過90%,不受譬如雨雪或結冰等天氣因素的影響。同時,交變磁場只有當車輛在充電板上方時才會產生,且不對人體或動物構成傷害。未來利用感應線圈的充電原理,奧迪電動汽車不僅可以在駛入車位後自動開始充電,甚至可以在設有感應線圈的公路上,一邊行駛一邊充電。  
    六、特斯拉   在19世紀90年代,尼古拉•特斯拉發明瞭“特斯拉線圈”,能夠通過空氣傳播電力,開啟了無線式電力傳播的時代。在“2011年國際消費電子展”上,美國安利公司旗下子公司富爾頓創新公司展示了無線充電技術,並推出了世界上第一輛無線充電的特斯拉汽車。目前,特斯拉希望能在各個大城市中建立起一張張相互連接的充電網,以解決電動車很容易出現的電力不足問題。   (圖片來源:EEPW)

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

    ※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    ※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

    ※教你寫出一流的銷售文案?

  • 北汽與Amber Dual合資逾2億人民幣 建馬來西亞電動車工廠

    據馬來西亞媒體5月19日報導,北汽集團近日在其北京工廠與Amber Dual有限公司簽訂了合資協議,雙方將投資2-3億元人民幣,在馬來西亞吉打州建立一座新廠,並將耗資約5,000萬元人民幣用於研發,預計於明年7月份開始生產。   此馬來西亞廠將作為北汽在東南亞地區的電動車生產中心。北汽為該工廠設定的電動車年產量目標為2,000到3,000輛,此後將逐漸遞增。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

    ※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

    ※帶您來看台北網站建置,台北網頁設計,各種案例分享

    ※別再煩惱如何寫文案,掌握八大原則!

  • 西安電動計程車要試運營啦!6月5日首批亮相36輛

    陝西省西安市首批36輛比亞迪e6電動計程車將於6月5日投入試運營。電動計程車可享受社會公共停車場2小時內免費停車,且西汽公司將建的士大廳,供駕駛員就餐休息。西安市一共購進了300輛電動計程車,其中西汽公司擁有90輛,由服務部代管,而這36輛將首批亮相。   為了滿足這些電動計程車充電,西汽總公司的院子裡已建成20個充電樁,將在22日投入使用。西汽服務部副經理張向東表示,由於現在部分充電站並未建成投入使用,因此公司會要求駕駛員在跑了200公里的時候就返回充電,這樣本來需要滿放滿充兩小時,最快充電可能幾十分鐘便可完成。而充電的費用將全部由公司承擔。   據工作人員介紹,雖然電動計程車的成本較高,但乘客乘坐電動計程車的價格初定與普通計程車一樣。按照政府推廣新能源車輛的相關規定,電動計程車不但能免交購置稅,而且可享受兩小時免費停車,隨時可走公交專用道。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    ※南投搬家前需注意的眉眉角角,別等搬了再說!

    ※新北清潔公司,居家、辦公、裝潢細清專業服務

  • 台達電與福特亮相CES Asia 推新型智慧電動車解決方案

    25日,台達電與福特汽車、海爾、天合光能攜手亮相首屆亞洲消費電子展(CES Asia),宣佈將四方聯合打造的「福特智•能生活」專案引入中國市場。此試點專案將在北京和上海兩個城市率先展開。福特及台達等合作夥伴將為試點家庭提供插電式混合動力汽車、智慧型交流充電樁、太陽能動力設備及智慧家電。   台達電在「福特智•能生活」專案中提供智慧型的電動車充電解決方案,並在福特展臺實地展示了壁掛式高效充電器產品。此壁掛式交流充電器已通過CQC/SRRC認證,採用防塵防水及防破壞機身設計,具備電壓、溫度等保護功能。充電器內建RFID讀卡機,可實現充電用戶身份辨識功能。充電器還內置乙太網通訊功能,可與充電站管理系統集成。   台達電動交通及雲端電源方案事業處總經理張育銘表示,福特這項計畫結合太陽能、家電和充電裝置,台達電導入家庭能源管理,讓電動車充電時用電不會超過既有容量,減少跳電的風險。此外,使用台達的充電裝置能遠端遙控,使用者可透過手機應用程式得知車輛是否充飽電,其還可採時間電價控制時程。   張育銘說,在政府補貼下,大陸電動車市場前景看好,未來幾年每年成長至少都有30%至50%。他表示,台達電開發電動車充電裝置近3年,原本就有和福斯(VW)和富豪(Volvo)合作,今年在大陸的交流充電器銷量預計達4000至5000台,遠高於2014年的數百台。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※別再煩惱如何寫文案,掌握八大原則!

  • 用Visual C++創建WPF項目的三種主要方法

    用Visual C++創建WPF項目的三種主要方法

    用Visual C++創建WPF項目的三種主要方法

    The problem with using XAML from C++

    Because C++ doesn’t support partial class definitions, it isn’t possible to directly support XAML in VC++ projects using this mechanism. That isn’t, however, the core reason why VC++ doesn’t directly support XAML. In addition to using the x:Class attribute, you can also use the x:Subclass attribute so that the XAML gets compiled into the class specified by the x:Class attribute, and the code behind will define the class specified by x:Subclass, which will be derived from the x:Class type. Thus, the lack of partial classes isn’t that big of a block. The main issue is that, right now, no 100-percent CodeDOM support is available to convert

    the XAML to C++, and that is the single biggest reason why VC++ doesn’t support XAML intrinsically. I don’t know this for sure, but it’s possible that on a later date, the Visual C++ team may work on their CodeDOM support and provide a fully functional XAML-to-C++ converter. Once that’s available, XAML support can be integrated into VC++ projects. As of today, however, that isn’t an option.

    NOTE: CodeDOM is a term used to represent a bunch of types available in the System.

    CodeDom namespace that lets you abstract code into an object model. Source code is represented using the CodeDOM tree and can be converted into source code for a specific language using the CodeDOM code generator for that specific language.

    Still, the fact that you can’t directly use XAML in a Visual C++ project doesn’t mean that WPF applications can’t be written with Visual C++.

    Three ways to write WPF apps using VC++

    You can use three different approaches to write WPF applications using Visual C++. Each has its pros and cons, and we’ll cover each of these approaches in the next section:

    • Use procedural code.

    For one thing, you can directly use procedural code to

    write Avalon-based applications and avoid using XAML. Of course, if you

    do that, you automatically give up the advantages of declarative programming

    that XAML brings in, but for certain scenarios, procedural code often

    serves the purpose well.

    • Dynamically load XAML.

    Alternatively, you can dynamically load XAML during runtime to create your Avalon windows, although the disadvantage is that you’d be distributing a bunch of XAML files with your application.

    • Derive from a class in a C# DLL

    A third technique uses a C# project to create your XAML-based Avalon controls and have a class (or classes) in your C++ project that derives from the classes in the C#-based Avalon DLL. With that mechanism, the UI is created using XAML in the C# project, and the business logic is kept in the C++ project.

    When you’re developing WPF applications with C++, you can use one or more of these approaches to achieve whatever functionality you want. In the next section, you’ll see how to write a simple WPF app with C++/CLI using each of the three techniques mentioned here.

    7.2 Using C++/CLI to write a WPF application

    If Visual C++ doesn’t have support for XAML, and there are no project templates for building an Avalon application (as of the June 2006 CTP), how much extra effort does it take to write Avalon applications using C++? In this section, you’ll find out. You’ll put the three different techniques I described at the end of section

    7.1.2 into action. All three mechanisms have their advantages and disadvantages; you can decide which is most suitable for your specific scenario. First, though, let’s briefly go over how to create a new C++/CLI project for Avalon.

    7.2.1 Creating a new C++/CLI Avalon project

    Avalon is a managed framework, and as such any Visual C++ project that needs to access and use Avalon needs to have the /clr compilation mode turned on.

    Creating a new C++/CLI project with support for Avalon is fortunately not a difficult task. Table 7.1 lists the few simple steps you need to follow each time you create an application (or library, as the case might be) that uses Avalon.

    Table 7.1 Steps to create a C++/CLI Avalon project

    Step Action How To
    1 Generate a new project Using the application wizard, specify the CLR Empty Project template.
    2 Set the SubSystem to /SUBSYSTEM:WINDOWS Apply this change in the Project properties, Linker settings, System sub-setting.
    3 Set the Entry Point to main From Project properties, choose Linker settings and then the Advanced sub-setting.
    4 Add references to the following assemblies: System PresentationCore PresentationFramework WindowsBase Note: Except for System, the other three are required for Avalon.

    At this point, your empty project is ready for writing Avalon code. Of course, you don’t have any code yet to compile, but you’ll fix that soon.

    7.2.2 Using procedural code

    You’ll now write your first Avalon application using C++/CLI, and you’ll do so entirely using procedural code. Think of it as analogous to an instruction book for putting together a table that contains only textual instructions (analogous to the procedural code) and no pictures (analogous to the XAML).

    Create a new CLR project using the steps outlined in the previous section, and add an App.cpp file to it (you can call it whatever you want). Listing 7.2 shows the code for the simplest Avalon application that shows a window onscreen.

    Listing 7.2 A simple Avalon app in procedural code

    If you compile and run the application, you’ll see a window onscreen that can be moved, resized, minimized, maximized, and closed. Avalon requires you to set the COM threading model to single threaded apartment (STA). You do so using the STAThread attribute on the main function ①. You then create a new instance of the Application object (using gcnew) and invoke the Run method on that instance, passing in a new instance of a Window object (again using gcnew) ②. The Application class represents an Avalon application and provides the core functionality for running the application. It has a Run method that is called to initiate the application’s main thread. The Run method has an overload that accepts a Window object, which you use in the code. This overload launches the application and uses the specified Window as the main application window. The Window class represents the core functionality of a window and by default provides you with basic windowing functionality such as moving, resizing, and so on, which you verified when you ran the application and saw a fully functional window onscreen.

    Note: Those of you who have an MFC background may see a faint similarity between this model and MFC, where the CWinApp class is analogous to the Application class, and the CFrameWnd class is analogous to the Window

    class. CWinApp has a Run method that provides the default message loop, and Application::Run does something similar. Of course, you shouldn’t infer too much from these minor similarities because they’re totally different UI programming models, but it’s possible that a similar design model was used by the architects of Avalon.

    This little program doesn’t have a lot of functionality; it just uses the default Window object to create and show a window onscreen. Let’s write a more refined application with its own Application-derived object as well as a window with some controls. Figure 7.4 shows a screenshot of what the enhanced application

    will look like.

    The main steps involved would be to derive two classes-one from the Window class, and the other from the Application class. You’ll start with the Window-derived class.

    Figure 7.4

    Enhanced WPF app in C++ (procedural code)

    Writing the Window-derived class

    The first thing you’ll do is add a new class called FirstWindow to your project, which will be derived from the Window class. You’ll also add some member variables for the various controls and set some of the window properties in the constructor. Listing 7.3 shows the code once you’ve done that.

    Listing 7.3 A more functional Avalon app in procedural code

    using namespace System;
    
    using namespace System::Windows;
    
    using namespace System::Windows::Controls;
    

    It’s much like Windows Forms programming, except that the controls you declare ①. are from the System::Windows::Controls namespace (which contains various WPF controls). You set properties like Title, Width, Height, and so on on the window object in the constructor ②. There’s also a call to a method called InitControls ③, where you initialize the child controls (I put it into a separate method to improve the code’s readability). Listing 7.4 shows the InitControls method. Basically, you instantiate each of the child controls, instantiate a container control, add the child controls to the container controls, and finally set the container control as the main Content of the parent window.

    Listing 7.4 Function to initialize the Avalon controls

    void InitControls(void)
    
    {
          listbox = gcnew ListBox();
          listbox->Width = 180;
    
          listbox->Height = 350;
    
          Canvas::SetTop(listbox, 10);
    
          Canvas::SetLeft(listbox, 10);
    
          textbox = gcnew TextBox();
    
          textbox->Width = 180;
    
          textbox->Height = 25;
        
          Canvas::SetTop(textbox, 10);
    
          Canvas::SetLeft(textbox, 200);
    
          addbutton = gcnew Button();
    
          addbutton->Width = 80;
    
          addbutton->Height = 25;
    
          addbutton->Content = "Add";
    
          Canvas::SetTop(addbutton, 45);
    
          Canvas::SetLeft(addbutton, 200);
    
          addbutton->Click += gcnew RoutedEventHandler(this, &FirstWindow::OnAddButtonClick);
    
          maincanvas = gcnew Canvas();
    
          maincanvas->Children->Add(listbox);
    
          maincanvas->Children->Add(textbox);
    
          maincanvas->Children->Add(addbutton);
    
          Content = maincanvas;
    }
    

    Again, you probably notice the similarity with Windows Forms programming.

    You instantiate the child controls ①, ②, and ③, and set various properties like Width and Height, and you also use the Canvas::SetTop and Canvas::SetLeft methods to position them on their container. For the button control, you also add an event handler for the Click event ④. Then, you instantiate the Canvas control (which is a container control for other child controls) and add the child controls as its children ⑤. Finally, you set the Content property of the window to this Canvas control ⑥.

    Now, you need to add the Click event handler for the button control, where you add the text entered into the TextBox to the ListBox:

    void OnAddButtonClick(Object^ sender, RoutedEventArgs^ e)
    {
    ​	listbox->Items->Add(textbox->Text);
    ​	textbox->Text = "";
    ​	textbox->Focus();
    }
    

    Notice that you set the text of the TextBox to an empty string once you’ve added it to the ListBox. You also call the Focus() method so that the user can continue

    adding more entries into the ListBox. The Window-derived class is ready. Let’s now write the Application-derived class.

    Writing the Application-derived class

    You derive a class called FirstApp from Application and add an override for the OnStartup method where you create and show the main window:

    #include "FirstWindow.h"
    
    ref class FirstApp : Application
    {
    public:
    FirstApp(void){}
    
    protected:
          virtual void OnStartup(StartupEventArgs^ e) override
          {
              Application::OnStartup(e);
              FirstWindow^ mainwnd = gcnew FirstWindow();
              mainwnd->Show();
          }
    };
    

    The OnStartup method is called, not surprisingly, when the application has just started. You override that function so that you can instantiate and show the window.

    The base function is responsible for invoking any event handlers associated with the Startup event, and thus you need to call the base method in the override.

    Now, all that’s left is to modify the main function to use the custom Application object instead of the default, as shown here:

    #include "FirstApp.h"
    
    [STAThread]
    
    int main(array<String^>^ args)
    {
    	return (gcnew FirstApp())->Run();
    }
    

    Notice that you don’t specify a window object to the Run method, because the window object is created in the OnStartup override of your Application-derived class.

    Compile and run the application, and try entering some text into the TextBox and clicking the Add button. You should see the text being entered into the ListBox.

    When you use procedural code with Avalon, it’s much like using Windows Forms, where you derive classes from the default controls, set some properties, add some event handlers, and are done. Procedural code is all right to develop WPF applications for simple user interfaces, but sometimes it makes better sense

    to take advantage of XAML and declarative programming. As I’ve mentioned a few times already, XAML isn’t directly supported in VC++, so you’ll have to look at alternate options to make use of XAML. One such option is to dynamically load the XAML at runtime.

    7.2.3 Dynamically loading XAML

    In this section, you’ll rewrite the application you wrote in the previous section, using dynamically loaded XAML. This way, you get to leverage the power of XAML and declarative programming (which you couldn’t in the procedural code technique you used in the previous section). Continuing the instruction-book analogy, this will be like one that has textual instructions that refer to pictures (which describe the various steps needed) and are loosely distributed along with the book but not directly printed in the book. You’ll define the UI using XAML instead of procedural code. When you’re done, you’ll have an identical application

    to the one you previously created.

    Create a new C++/CLI Avalon project using the steps mentioned in the introduction to section 7.2, and call it FirstAvalonDynamic (or whatever you want to call it). The first thing you’ll do is write the XAML (MainWindow.xaml) that represents the UI; see listing 7.5.

    Listing 7.5 XAML for the main window

    <Window
    
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    
         Title="First Avalon App (dynamically load XAML)"
    
         Height="400" Width="400"
    
         ResizeMode="NoResize"
    
         > 
    
         <Canvas>
               <ListBox Canvas.Left="10" Canvas.Top="10"
                     Width="180" Height="350"
                     Name="listbox" />
                   <TextBox Canvas.Left="200" Canvas.Top="10"
                     Width="180" Height="25"
                     Name="textbox" />
               <Button Canvas.Left="200" Canvas.Top="45"
                     Width="80" Height="25"
                     Name="addbutton">Add</Button>
         </Canvas>
    </Window>
    

    The XAML shown does exactly what you did with the procedural code earlier. For the control elements, you use the same names using the Name attribute as you use for the member variables in the procedural code. Next, you need to hook an event handler to the Button so that the text entered into the TextBox is inserted

    into the ListBox. For that, you’ll write a helper class, as shown in listing 7.6.

    Listing 7.6 WindowHelper class that implements the event handler

    using namespace System;
    
    using namespace System::Windows;
    
    using namespace System::Windows::Controls;
    
    using namespace System::Windows::Markup;
    
    using namespace System::IO;
    
    ref class WindowHelper
    {
    
         ListBox^ listbox;
    
         TextBox^ textbox;
    
         Button^ addbutton;
    
    
    
    public:
    WindowHelper(Window^ window)
    {
       addbutton = (Button^)window->FindName("addbutton");
    
       textbox = (TextBox^)window->FindName("textbox");
    
       listbox = (ListBox^)window->FindName("listbox");
    
       addbutton->Click += gcnew RoutedEventHandler(
    
       this,&WindowHelper::OnAddButtonClick);
    }
    
    void OnAddButtonClick(Object^ sender, RoutedEventArgs^ e)
    {
       listbox->Items->Add(textbox->Text);
    
       textbox->Text = "";
    
       textbox->Focus();
    }
    
    };
    

    The WindowHelper constructor accepts a Window argument and uses the FindName method ① to get the control with the specified identifier (which maps to the Name attributes you used in the XAML). You also hook an event handler to the addbutton control ②. Finally, you have the event handler③, which is identical to the one you used in the procedural code project. Listing 7.7 shows the code for the Application-derived class, where you override OnStartup as before, except that you create a window dynamically by loading the XAML file from the disk.

    Listing 7.7 The Application-derived class

    ref class FirstAppDynamic : Application
    
    {
    
    public:
    
         FirstAppDynamic(void)
         {
    
         }
    
    protected:
         virtual void OnStartup(StartupEventArgs^ e) override
         {
    
               Application::OnStartup(e);
    
               Stream^ st = File::OpenRead("MainWindow.xaml");
    
               Window^ mainwnd = (Window^)XamlReader::Load(st);
    
               st->Close();
    
               WindowHelper^ mainwndhelper = gcnew WindowHelper(mainwnd);
    
               mainwnd->Show();
    
         }
    
    };
    
    

    You open a file stream to the XAML using File::OpenRead ① and use the overload of XamlReader::Load ② that takes a Stream^ as parameter to create a Window object. This Load method works the magic, by reading and parsing the XAML and building a Window object out of it. You instantiate the WindowHelper object and pass

    this Window object as the argument, so that the event handler for the addbutton control is properly set up ③. You then show the window ④ with a call to Show().

    The main method is much the same as before, where you instantiate the Application object and call Run on it:

    [STAThread]
    int main(array<String^>^ args)
    {
    
          return (gcnew FirstAppDynamic())->Run();
    
    }
    

    The advantage of using this technique over using procedural code is that you get to design your UI in XAML, thereby achieving a level of UI/code separation. You can also use Cider or some other XAML designer to quickly design flexible user interfaces, which would involve a good bit of hand-coding in procedural code.

    The disadvantage is that you have to distribute the XAML file with your application, and if you have multiple windows, you then need that many XAML files.

    There’s always the risk of a loosely-distributed XAML file getting corrupted (accidentally or otherwise) or even being deleted. You can embed all the XAML files as resources in the C++/CLI assembly and load them at runtime, but even that involves a lot of extra work. To avoid distributing XAML files loosely with your

    application or embedding them as resources, you may want to use the technique we’ll discuss in the next section: putting the XAML into a C# project and accessing it via a derived class in a C++ project.

    7.2.4 Deriving from a class in a C# DLL

    You’ll write a third variation of the same application in this section. You’ll use a C# control library project for the XAML, and a C++ project that will utilize that XAML control by deriving a control from it. Using the instruction-book analogy again, this is essentially a picture-based, step-by-step guide with the textual

    instructions printed alongside each picture providing some meta-information for the step indicated by that picture. First, use the New Project Wizard to generate a new C# .NET 3.0 Custom Control Library project, and delete the default XAML file generated by the wizard. The default XAML is derived from User-

    Control and isn’t what you want. Add a new XAML file to the C# project that represents a Window, and either use Cider or hand-code the XAML from listing 7.8 into that file.

    Listing 7.8 The Window class definition using XAML

    <Window x:Class="CSXamlLibrary.BaseWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="First Avalon App (dynamically load XAML)"
         Height="400" Width="400"
         ResizeMode="NoResize"
         > 
    
         <Canvas>
               <ListBox Canvas.Left="10" Canvas.Top="10"
                     Width="180" Height="350"
                     Name="listbox" x:FieldModifier="protected" />
    
               <TextBox Canvas.Left="200" Canvas.Top="10"
                     Width="180" Height="25"
                     Name="textbox" x:FieldModifier="protected" />
    
               <Button Canvas.Left="200" Canvas.Top="45"
                     Width="80" Height="25"
                     Name="addbutton" x:FieldModifier="protected">Add</Button>
         </Canvas>
    
    </Window>
    

    The XAML is identical to that used in the previous project (where you dynamically loaded it) except for the x:Class attribute for the Window element, which specifies the name of the class that will be generated, and the x:FieldModifier attributes that are applied to the child control elements so they’re generated as protected members in the class (rather than as private which is the default). Build the C# project, and generate the control library. Once that’s done, create a new C++/CLI Avalon project (using the same steps as before), and then add a reference to this C# project. Now, you can write a new Window class that’s derived from the class in the C# DLL, as shown in listing 7.9.

    Listing 7.9 Deriving the main window from the XAML-defined Window class

    using namespace System;
    
    using namespace System::Windows;
    
    using namespace System::Windows::Controls;
    
    
    
    ref class AppMainWindow : CSXamlLibrary::BaseWindow
    {
         public:
               AppMainWindow(void)
               {
                     addbutton->Click += gcnew RoutedEventHandler(this, &AppMainWindow::OnAddButtonClick);
               }
    
               void OnAddButtonClick(Object^ sender, RoutedEventArgs^ e)
               {
    
                     listbox->Items->Add(textbox->Text);
    
                     textbox->Text = "";
    
                     textbox->Focus();
    
               }
    
    };
    

    The code is similar to what you’ve seen thus far, except that it’s a lot cleaner.

    Unlike the first example, you don’t have a lot of clogged procedural code to create the UI. Unlike the second example, you don’t need a helper class to map the XAML elements to the control variables and event handlers. It’s definitely an improvement over the previous two examples, but you have to bring in the C#

    project just for the XAML. The rest of the code needed for the application is more or less similar to what you saw earlier:

    ref class FirstAppDerived : Application
    {
          protected:
                virtual void OnStartup(StartupEventArgs^ e) override
                {
                      Application::OnStartup(e);
                      AppMainWindow^ mainwnd = gcnew AppMainWindow();
                      mainwnd->Show();
                }
    
    };
    
    [STAThread]
    
    int main(array<String^>^ args)
    {
          return (gcnew FirstAppDerived())->Run();
    }
    

    In some ways, the third technique is a sort of hybrid of the previous two techniques.

    A lot of the code is identical to that in the first technique – as with the declaration of a custom class derived from Window and an Application-derived class with the OnStartup method creating the custom window. But, like the second technique, the UI definition is in the XAML, except that in this case, it’s compiled into the C# DLL. You also reduce lines of code with each successive technique. You had the most lines of code with procedural code (as is to be expected) and improved on that considerably when you moved the UI definition to the XAML in the dynamically-loaded XAML example. In the last example, you saved even further on lines of code, such as the helper class from the second example that had to wire the XAML elements to the member variables. Of course, the total lines of code (LOC) isn’t always the single deciding factor that determines what technique you choose. Table 7.2 shows a comparison of the three techniques; for each factor, the cells with the bold text reflect the technique (or techniques) that offer maximum performance (or convenience).

    Table 7.2 Comparison of the three techniques

    Procedural code Dynamically load XAML XAML in C# DLL
    Cluttered code that generates the UI Yes No No
    Dependency on loose XAML files No Yes No
    Dependency on C#-based DLL No No Yes
    Lines of code Maximum In-between Minimum
    UI design convenience Poor Excellent Excellent
    UI/business logic separation Poor Good Excellent
    Level of Visual C++ project support Total Partial (Not applicable)

    It’s hard to pinpoint a specific technique and claim that it’s the best one, because depending on your requirements, each has advantages and disadvantages. Of course, in the future, if Visual C++ has direct support for XAML (as I believe it will), that will be your best option for the majority of scenarios.

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?