How to prevent UI Flickering

  1. Create winform below code
protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;  // WS_EX_COMPOSITED
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }

WS_EX_COMPOSITED works by forcing child windows to draw back to front and by double buffering them;  (더블버터링을 위해서는 위 옵션을 사용한다.)

2. Set Double Buffering

this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer,
true);

C# Run application with administrator permission

  1. Select your project
  2. Alt+Enter(view Attribute)
  3. Off ClickOnce Security
  4. Open app.minifest which is created
  5. delete this code

delete <requestExcutionLevel level=”asInvoker” uiAccess=”false”/>

Add this code!!!!

<requestExcutionLevel level=”highestAvailable” uiAccess=”false”/>

That’s all!

[C#] – SetThreadExecutionState function

ValueMeaning
ES_AWAYMODE_REQUIRED0x00000040Enables away mode. This value must be specified with ES_CONTINUOUS.Away mode should be used only by media-recording and media-distribution applications that must perform critical background processing on desktop computers while the computer appears to be sleeping. See Remarks.
ES_CONTINUOUS0x80000000Informs the system that the state being set should remain in effect until the next call that uses ES_CONTINUOUS and one of the other state flags is cleared.
ES_DISPLAY_REQUIRED0x00000002Forces the display to be on by resetting the display idle timer.
ES_SYSTEM_REQUIRED0x00000001Forces the system to be in the working state by resetting the system idle timer.
ES_USER_PRESENT0x00000004This value is not supported. If ES_USER_PRESENT is combined with other esFlags values, the call will fail and none of the specified states will be set.

The system automatically detects activities such as local keyboard or mouse input, server activity, and changing window focus. Activities that are not automatically detected include disk or CPU activity and video display.

Calling SetThreadExecutionState without ES_CONTINUOUS simply resets the idle timer; to keep the display or system in the working state, the thread must call SetThreadExecutionStateperiodically.

To run properly on a power-managed computer, applications such as fax servers, answering machines, backup agents, and network management applications must use both ES_SYSTEM_REQUIRED and ES_CONTINUOUS when they process events. Multimedia applications, such as video players and presentation applications, must use ES_DISPLAY_REQUIRED when they display video for long periods of time without user input. Applications such as word processors, spreadsheets, browsers, and games do not need to callSetThreadExecutionState.

The ES_AWAYMODE_REQUIRED value should be used only when absolutely necessary by media applications that require the system to perform background tasks such as recording television content or streaming media to other devices while the system appears to be sleeping. Applications that do not require critical background processing or that run on portable computers should not enable away mode because it prevents the system from conserving power by entering true sleep.

To enable away mode, an application uses both ES_AWAYMODE_REQUIRED and ES_CONTINUOUS; to disable away mode, an application calls SetThreadExecutionState with ES_CONTINUOUS and clears ES_AWAYMODE_REQUIRED. When away mode is enabled, any operation that would put the computer to sleep puts it in away mode instead. The computer appears to be sleeping while the system continues to perform tasks that do not require user input. Away mode does not affect the sleep idle timer; to prevent the system from entering sleep when the timer expires, an application must also set the ES_SYSTEM_REQUIRED value.

The SetThreadExecutionState function cannot be used to prevent the user from putting the computer to sleep. Applications should respect that the user expects a certain behavior when they close the lid on their laptop or press the power button.

[C#] – SystemEvents Class

SystemEvents 클래스는 특정 유형의 시스템 이벤트에 응답 하는 기능을 제공 합니다.

using System;
using Microsoft.Win32;

public sealed class App 
{
    static void Main() 
    {         
        // Set the SystemEvents class to receive event notification when a user 
        // preference changes, the palette changes, or when display settings change.
        SystemEvents.UserPreferenceChanging += new 
            UserPreferenceChangingEventHandler(SystemEvents_UserPreferenceChanging);
        SystemEvents.PaletteChanged += new 
            EventHandler(SystemEvents_PaletteChanged);
        SystemEvents.DisplaySettingsChanged += new 
            EventHandler(SystemEvents_DisplaySettingsChanged);        

        // For demonstration purposes, this application sits idle waiting for events.
        Console.WriteLine("This application is waiting for system events.");
        Console.WriteLine("Press <Enter> to terminate this application.");
        Console.ReadLine();
    }

    // This method is called when a user preference changes.
    static void SystemEvents_UserPreferenceChanging(object sender, UserPreferenceChangingEventArgs e) 
    {
        Console.WriteLine("The user preference is changing. Category={0}", e.Category);
    }

    // This method is called when the palette changes.
    static void SystemEvents_PaletteChanged(object sender, EventArgs e)
    {
        Console.WriteLine("The palette changed.");
    }

    // This method is called when the display settings change.
    static void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
    {
        Console.WriteLine("The display settings changed.");
    }
}

// This code produces the following output.
// 
//  This app is waiting for system events.
//  Press <Enter> to terminate this application.
//  Display Settings changed.
//  User preference is changing. Category=General

[출처]
https://docs.microsoft.com/ko-kr/dotnet/api/microsoft.win32.systemevents?view=netframework-4.7.2

[C#]-Detect Event When Lid Open/Close

protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_POWERBROADCAST:
                    OnPowerBroadcast(m.WParam, m.LParam);
                  
                    
                    switch (m.WParam.ToInt32())
                    {
                        case PBT_APMPOWERSTATUSCHANGE:
                          // Disconnect Power Cable
                           
                        break;

                        case PBT_APMQUERYSUSPEND:
                        case PBT_APMSUSPEND:
                            IntPtr deny = new IntPtr(BROADCAST_QUERY_DENY);
                            if (deny != null)
                            {
                                m.Result = deny;
                            }
                            break;          
                    }
                    
                    break;
                default:
                    break;
            }
            base.WndProc(ref m);
        }
private void OnPowerBroadcast(IntPtr wParam, IntPtr lParam)
        {
            bool isTurnOnSound = false;

            Debug.WriteLine("OnPowerBroadcast: " + wParam);
            
            if ((int)wParam == PBT_POWERSETTINGCHANGE)              // 32787
            {
                POWERBROADCAST_SETTING ps = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(lParam, typeof(POWERBROADCAST_SETTING));
                IntPtr pData = (IntPtr)((int)lParam + Marshal.SizeOf(ps));
                Int32 iData = (Int32)Marshal.PtrToStructure(pData, typeof(Int32));
                

                if (ps.PowerSetting == GUID_LIDSWITCH_STATE_CHANGE)
                {
                    bool isLidOpen = ps.Data != 0;

                    if (!isLidOpen == _previousLidState)
                    {
                        if( !isLidOpen )    // When Lid Close
                        {
                             // TODO
                        }
                    }

                    _previousLidState = isLidOpen;
                }
        
            }
        }

[C#] – WndProc

메세지 처리함수

메시지 처리 함수란 메시지가 발생할 때 프로그램의 반응을 처리하는 일을 하며 WinMain 함수와는 별도로 WndProc이라는 이름으로 존재한다.

윈도우 프로시저(Window Procedure)라는 뜻이지만 통상 읽을 때는 “윈드프록“이라고 읽는다. WndProc은 WinMain에서 호출하는 것이 아니라 윈도우즈에 의해 호출된다. WinMain내의 메시지 루프는 메시지를 메시지 처리 함수로 보내주기만 할 뿐이며 WndProc은 메시지가 입력되면 윈도우즈에 의해 호출되어 메시지를 처리한다.

이렇게 운영체제에 의해 호출되는 응용 프로그램내의 함수를 콜백(CallBack) 함수라고 한다. WndProc의 인수는 모두 4개이며 MSG 구조체의 멤버 4개와 동일하다. hWnd는 메시지를 받을 윈도우의 핸들이며 iMessage는 어떤 종류의 메시지인가, 즉 어떤 변화가 발생했는가에 관한 정보를 가진다. iMessage가 WM_MOVE이면 윈도우의 위치가 변경되었음을 알리고 WM_DESTROY이면 윈도우가 파괴되었음을 알리는 것이다. wParam, lParam은 iMessage의 메시지에 따른 부가적인 정보를 가진다. 예를 들어 마우스 버튼이 눌러졌다는 WM_LBUTTONDOWN 메시지가 입력되었다면 화면의 어디쯤에서 마우스 버튼이 눌러졌는가, 그때의 키보드 상황(Shift, Ctrl, Alt)은 어떠한가에 관한 정보가 추가로 필요하며 WM_CHAR 메시지, 즉 키보드로부터 키가 입력되었다는 메시지가 입력되었다면 어떤 키가 입력되었는가에 관한 추가적인 정보가 필요하다. 이런 추가 정보들이 wParam, lParam으로 전달된다. wParam, lParam에 실제로 어떤 값을 전달되는지는 메시지별로 다르다. WndProc의 구조는 대체로 다음과 같은 형태를 가진다. 메시지의 종류에 따라 다중 분기하여 메시지별로 처리를 진행한다.
switch(iMessage) 
{ 
     case Msg1: 
         처리1;
         return 0; 
     case Msg2: 
         처리2;
         return 0;
     case Msg3: 
         처리3; 
         return 0; 
     default: 
         return DefWindowProc(...);
} 

Msg1 메시지가 전달되면 처리1을 한 후 리턴하고 Msg2 메시지가 전달되면 처리2를 한 후 리턴한다. case문은 프로그램이 처리할 메시지의 수만큼 반복될 것이다. 제일 끝에 있는 DefWindowProc 함수는 WndProc에서 처리하지 않은 나머지 메시지에 관한 처리를 해 준다. 예를 들어 시스템 메뉴를 더블 클릭하면 프로그램이 종료되는데 이런 처리는 별도로 해 주지 않아도 DefWindowProc 함수에서 해 준다. 그래서 윈도우의 이동이나 크기변경 따위의 처리는 직접 해 줄 필요없이 DefWindowProc으로 넘겨주기만 하면 된다.

First 예제의 메시지 처리 함수는 다음과 같이 되어 있다.

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam) 
{ 
     switch(iMessage)
    { 
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }
    return(DefWindowProc(hWnd,iMessage,wParam,lParam));
 } 

WM_DESTROY 메시지만을 처리하고 있으며 나머지 메시지에 대해서는 DefWindowProc에게 맡긴다. WM_DESTROY 메시지는 사용자가 시스템 메뉴를 더블클릭하거나 Alt+F4를 눌러 프로그램을 끝내려고 할 때 발생하는 메시지이다. WndProc에서 이 메시지가 발생하면 PostQuitMessage 함수를 호출하여 WM_QUIT 메시지를 보낸다. WM_QUIT 메시지가 입력되면 메시지 루프의 GetMessage 함수 리턴값이 False가 되어 프로그램이 종료된다.WM_DESTROY 이외의 메시지는 모두 DefWindowProc 함수로 전달되며 이 함수에서 디폴트 처리를 수행해 준다. WndProc은 메시지를 처리했을 경우 반드시 0을 리턴해 주어야 한다. 또한 DefWindowProc 함수가 메시지를 처리했을 경우 이 함수가 리턴한 값을 WndProc 함수가 다시 리턴해 주어야 한다.

[출처]:http://soen.kr/lecture/win32api/lec2/lec2-2-4.htm

[C#] – PC Power Detect

Registering for Power Events

Applications can better adapt their behavior to the current power state of the computer by registering for power events. An application should register for each power change event that might impact its behavior.

An application or service uses the RegisterPowerSettingNotification function to register for notifications. When the corresponding power setting changes, the system sends notifications as follows:

In the POWERBROADCAST_SETTING structure, the PowerSetting member contains the GUID that identifies the notification and the Data member contains the new value of the power setting.

For a list of power setting GUIDs for notifications that are most useful to applications, see Power Setting GUIDs.

https://docs.microsoft.com/ko-kr/windows/desktop/Power/registering-for-power-events